コード例 #1
0
/*
 * net_buffer_condition_callback
 * @data: Unused parameter.
 * Function that will be called when networking condition is valid.
 */
static void net_buffer_condition_callback(void *data)
{
    FS_BUFFER *buffer;
    FD buffer_fd;

    /* Remove a compiler warning. */
    UNUSED_PARAM(data);

    /* Read a buffer pointer from the file descriptor. */
    if (fs_read(net_buff_fd, (uint8_t *)&buffer, sizeof(FS_BUFFER *)) == sizeof(FS_BUFFER *))
    {
        /* Save the file descriptor on which data was received. */
        buffer_fd = buffer->fd;

        /* TODO: This is quite expensive. */
        /* Obtain lock for the file descriptor on which this semaphore was
         * received, this is required as the buffer will return it's
         * segments to the original file descriptor when applicable. */
        OS_ASSERT(fd_get_lock(buffer_fd) != SUCCESS);

        /* Process this buffer. */
        if (net_buffer_process(buffer) != NET_BUFFER_CONSUMED)
        {
            /* Free this buffer. */
            fs_buffer_add_buffer_list(buffer, FS_BUFFER_LIST, FS_BUFFER_ACTIVE);
        }

        /* Release semaphore for the buffer. */
        fd_release_lock(buffer_fd);
    }

} /* net_buffer_condition_callback */
コード例 #2
0
/*
 * enc28j60_atmega644p_reset
 * device: ENC28J60 device needed to be reset.
 * This function will reset the target enc28j60 device.
 */
void enc28j60_atmega644p_reset(ENC28J60 *device)
{
    FD *fd = (FD)device;

    /* Clear the RST, i.e. PD.4. */
    PORTD &= (uint8_t)~(1 << 4);

    /* Release lock for this device. */
    fd_release_lock(fd);

    /* Sleep to wait for target to actually reset. */
    sleep_ms(ENC28J60_ATMEGA644P_RESET_DELAY);

    /* Acquire lock for this device. */
    OS_ASSERT(fd_get_lock(fd) != SUCCESS);

    /* Set the RST, i.e. PD.4. */
    PORTD |= (1 << 4);

} /* enc28j60_atmega644p_reset */
コード例 #3
0
ファイル: tftps.c プロジェクト: n3rd-bugs/weird-rtos
/*
 * tftp_server_process
 * @data: TFTP server data for which a request is needed to be processed.
 * @resume_status: Resumption status.
 * This is callback function to process a request for a TFTP server.
 */
static void tftp_server_process(void *data, int32_t resume_status)
{
    TFTP_SERVER *tftp_server = (TFTP_SERVER *)data;
    FS_BUFFER_LIST *rx_buffer;
    uint32_t data_len;
    int32_t status = SUCCESS, received;
    uint16_t opcode, block;
    uint8_t last_block = FALSE, data_buffer[TFTP_BUFFER_SIZE];
    FD fd;

    /* Remove some compiler warnings. */
    UNUSED_PARAM(resume_status);

    SYS_LOG_FUNCTION_ENTRY(TFTPS);

    /* If the timeout was enabled and it has now occurred. */
    if ((tftp_server->port_suspend.timeout_enabled == TRUE) && (INT32CMP(current_system_tick(), tftp_server->port_suspend.timeout) >= 0))
    {
        /* If we have a connection. */
        if (tftp_server->fd != NULL)
        {
            /* Close the file descriptor. */
            fs_close(&tftp_server->fd);

            SYS_LOG_FUNCTION_MSG(TFTPS, SYS_LOG_INFO, "file transfered interrupted", "");
        }

        /* Reset the current timeout. */
        tftp_server->port_suspend.timeout = MAX_WAIT;
        tftp_server->port_suspend.timeout_enabled  = FALSE;
    }

    /* Receive incoming data from the UDP port. */
    received = fs_read(&tftp_server->port, (uint8_t *)&rx_buffer, sizeof(FS_BUFFER_LIST));

    /* If some data was received. */
    if (received >= (int32_t)sizeof(uint32_t))
    {
        /* Acquire lock for the buffer file descriptor. */
        ASSERT(fd_get_lock(rx_buffer->fd) != SUCCESS);

        /* Pull the opcode from the buffer. */
        status = fs_buffer_list_pull(rx_buffer, &opcode, sizeof(uint16_t), (FS_BUFFER_PACKED));

        if (status == SUCCESS)
        {
            SYS_LOG_FUNCTION_MSG(TFTPS, SYS_LOG_DEBUG, "received a request 0x%04X", opcode);

            /* Process the TFTP opcode. */
            switch (opcode)
            {
            /* Read request. */
            case TFTP_OP_READ_REQ:

            /* Write request. */
            case TFTP_OP_WRITE_REQ:

                /* If we can establish connection with a new client. */
                if (tftp_server->fd == NULL)
                {
                    /* Pull the file name from the frame. */
                    for (data_len = 0; ((status == SUCCESS) && (data_len < TFTP_BUFFER_SIZE)); data_len++)
                    {
                        /* Pull the filename from the buffer. */
                        status = fs_buffer_list_pull(rx_buffer, &data_buffer[data_len], sizeof(uint8_t), 0);

                        /* If filename was terminated. */
                        if (data_buffer[data_len] == '\0')
                        {
                            break;
                        }
                    }

                    /* If file name was successfully parsed. */
                    if ((status == SUCCESS) && (data_len < TFTP_BUFFER_SIZE))
                    {
                        /* Release lock for buffer file descriptor. */
                        fd_release_lock(rx_buffer->fd);

                        /* If read was requested. */
                        if (opcode == TFTP_OP_READ_REQ)
                        {
                            SYS_LOG_FUNCTION_MSG(TFTPS, SYS_LOG_INFO, "read requested for \"%s\"", data_buffer);

                            /* Open the required file. */
                            fd = fs_open((char *)data_buffer, (FS_READ));
                        }
                        else
                        {
                            SYS_LOG_FUNCTION_MSG(TFTPS, SYS_LOG_INFO, "write requested for \"%s\"", data_buffer);

                            /* Open the required file. */
                            fd = fs_open((char *)data_buffer, (FS_WRITE | FS_CREATE));
                        }

                        /* If file was not found or was not opened. */
                        if (fd == NULL)
                        {
                            /* A file system error was detected. */
                            status = TFTP_ERROR_FS;

                            SYS_LOG_FUNCTION_MSG(TFTPS, SYS_LOG_ERROR, "error opening file \"%s\"", data_buffer);
                        }
                        else
                        {
                            /* Save the opened file descriptor. */
                            tftp_server->fd = fd;

                            /* Save the client address. */
                            memcpy(&tftp_server->client_address, &tftp_server->port.last_datagram_address, sizeof(SOCKET_ADDRESS));

                            /* Initialize session variables. */
                            tftp_server->block_num = 0;
                            tftp_server->tx_block_len = 0;
                            tftp_server->last_block = FALSE;
                        }

                        /* Acquire lock for the buffer file descriptor. */
                        ASSERT(fd_get_lock(rx_buffer->fd) != SUCCESS);
                    }
                    else
                    {
                        /* File name was too long. */
                        status = TFTP_LONG_FILENAME;
                    }
                }
                else
                {
                    /* No more clients can be connected. */
                    status = TFTP_ERROR_EXHAUSTED;
                }

                break;

            /* Data request. */
            case TFTP_OP_DATA:

                /* If we have a open file and this is the client who opened it. */
                if ((tftp_server->fd != NULL) && (memcmp(&tftp_server->client_address, &tftp_server->port.last_datagram_address, sizeof(SOCKET_ADDRESS)) == 0))
                {
                    /* Pull the block number from the buffer. */
                    status = fs_buffer_list_pull(rx_buffer, &block, sizeof(uint16_t), (FS_BUFFER_PACKED));

                    if (status == SUCCESS)
                    {
                        /* If this is the last block. */
                        if (rx_buffer->total_length != TFTP_BLOCK_SIZE)
                        {
                            /* Mark this as last block. */
                            last_block = TRUE;
                        }

                        /* If client skipped a block. */
                        if (block > (tftp_server->block_num + 1))
                        {
                            /* This is an unknown block. */
                            status = TFTP_OUTOFBOUND_BLOCK;
                        }

                        /* If this is the anticipated block. */
                        else if (block == (tftp_server->block_num + 1))
                        {
                            /* While we have some data to write. */
                            while ((status == SUCCESS) && (rx_buffer->total_length > 0))
                            {
                                /* Pull some data from the buffer. */
                                data_len = ((rx_buffer->total_length > TFTP_BUFFER_SIZE) ? TFTP_BUFFER_SIZE : rx_buffer->total_length);
                                status = fs_buffer_list_pull(rx_buffer, data_buffer, data_len, 0);

                                if (status == SUCCESS)
                                {
                                    /* Release lock for buffer file descriptor. */
                                    fd_release_lock(rx_buffer->fd);

                                    /* Write a chuck on the file. */
                                    if (fs_write(tftp_server->fd, data_buffer, (int32_t)data_len) <= 0)
                                    {
                                        /* File error. */
                                        status = TFTP_ERROR_FS;
                                    }

                                    /* Acquire lock for the buffer file descriptor. */
                                    ASSERT(fd_get_lock(rx_buffer->fd) != SUCCESS);
                                }
                            }

                            if (status == SUCCESS)
                            {
                                /* Save the current block number. */
                                tftp_server->block_num = block;
                            }
                        }

                        /* In case this is a retransmission, just send an ACK. */

                        /* If this was the last block. */
                        if (last_block == TRUE)
                        {
                            /* Close the file descriptor. */
                            fs_close(&tftp_server->fd);

                            /* Stop the timer. */
                            tftp_server->port_suspend.timeout = MAX_WAIT;
                            tftp_server->port_suspend.timeout_enabled = FALSE;

                            SYS_LOG_FUNCTION_MSG(TFTPS, SYS_LOG_INFO, "file transfered successfully", "");
                        }
                    }
                }
                else
                {
                    /* Transaction ID is not known. */
                    status = TFTP_UNKNOWN_TID;
                }

                break;

            /* ACK was received. */
            case TFTP_OP_ACK:

                /* If we have a session open for this client. */
                if ((tftp_server->fd != NULL) && (memcmp(&tftp_server->client_address, &tftp_server->port.last_datagram_address, sizeof(SOCKET_ADDRESS)) == 0))
                {
                    /* Pull the block number from the buffer. */
                    status = fs_buffer_list_pull(rx_buffer, &block, sizeof(uint16_t), (FS_BUFFER_PACKED));

                    if (status == SUCCESS)
                    {
                        /* If other side has ACKed the block we  sent earlier. */
                        if (block == tftp_server->block_num)
                        {
                            /* If we just received ACK for the last block. */
                            if (tftp_server->last_block == TRUE)
                            {
                                /* Close the file descriptor. */
                                fs_close(&tftp_server->fd);

                                /* Stop the timer. */
                                tftp_server->port_suspend.timeout = MAX_WAIT;
                                tftp_server->port_suspend.timeout_enabled = FALSE;

                                SYS_LOG_FUNCTION_MSG(TFTPS, SYS_LOG_INFO, "file transfered successfully", "");

                                /* Nothing to be sent in reply. */
                                status = TFTP_FRAME_DROP;
                            }
                        }
                        else if (block > tftp_server->block_num)
                        {
                            /* This is an unknown block. */
                            status = TFTP_OUTOFBOUND_BLOCK;
                        }
                        else
                        {
                            /* Lets send the old frame again. */
                            /* TODO seek the file back 1 block. */

                            /* For now send an error. */
                            status = TFTP_ERROR_FS;
                        }
                    }
                }
                else
                {
                    /* Transaction ID is not known. */
                    status = TFTP_UNKNOWN_TID;
                }

                break;

            case TFTP_OP_ERR:

                /* If we have a session open for this client. */
                if ((tftp_server->fd != NULL) && (memcmp(&tftp_server->client_address, &tftp_server->port.last_datagram_address, sizeof(SOCKET_ADDRESS)) == 0))
                {
                    /* Close the file descriptor. */
                    fs_close(&tftp_server->fd);

                    /* Stop the timer. */
                    tftp_server->port_suspend.timeout = MAX_WAIT;
                    tftp_server->port_suspend.timeout_enabled = FALSE;

                    SYS_LOG_FUNCTION_MSG(TFTPS, SYS_LOG_INFO, "file transfered interrupted", "");
                }

                /* Lets drop this frame. */
                status = TFTP_FRAME_DROP;

                break;

            /* Unknown opcode. */
            default:

                SYS_LOG_FUNCTION_MSG(TFTPS, SYS_LOG_ERROR, "unknown or unsupported opcode 0x%04X", opcode);

                /* This opcode is not supported. */
                status = TFTP_NOT_SUPPORTED;

                break;
            }

            /* Discard any data in the buffer. */
            fs_buffer_list_pull(rx_buffer, NULL, rx_buffer->total_length, 0);

            /* If we have a session open for this client and we just received some data from it. */
            if ((tftp_server->fd != NULL) && (memcmp(&tftp_server->client_address, &tftp_server->port.last_datagram_address, sizeof(SOCKET_ADDRESS)) == 0))
            {
                /* Reset the timer to terminate this connection. */
                tftp_server->port_suspend.timeout = current_system_tick() + TFTP_CLI_TIMEOUT;
                tftp_server->port_suspend.timeout_enabled  = TRUE;
            }

            /* If request was processed successfully. */
            if (status == SUCCESS)
            {
                /* Process the request. */
                switch (opcode)
                {
                /* We successfully processed a write request. */
                case TFTP_OP_WRITE_REQ:
                case TFTP_OP_DATA:

                    /* Push the acknowledgment opcode. */
                    opcode = TFTP_OP_ACK;

                    break;

                /* We successfully processed a read request. */
                case TFTP_OP_READ_REQ:
                case TFTP_OP_ACK:

                    /* We will send file content in reply. */
                    opcode = TFTP_OP_DATA;

                    /* Send the next block. */
                    tftp_server->block_num++;

                    break;
                }

                /* Push required opcode on the buffer. */
                status = fs_buffer_list_push_offset(rx_buffer, &opcode, 2, 0, (FS_BUFFER_PACKED | FS_BUFFER_TAIL));

                if (status == SUCCESS)
                {
                    /* Push block we are transmitting or acknowledging. */
                    status = fs_buffer_list_push_offset(rx_buffer, &tftp_server->block_num, 2, 0, (FS_BUFFER_PACKED | FS_BUFFER_TAIL));
                }

                /* If we need to add data. */
                if (opcode == TFTP_OP_DATA)
                {
                    /* Add data block. */
                    for (data_len = 0; ((status == SUCCESS) && (data_len < TFTP_BLOCK_SIZE));)
                    {
                        /* Calculate the number of bytes we need to read. */
                        status = (int32_t)(((data_len + TFTP_BUFFER_SIZE) > TFTP_BLOCK_SIZE) ? (TFTP_BLOCK_SIZE - data_len) : (TFTP_BUFFER_SIZE));

                        /* Read a chunk of buffer. */
                        status = fs_read(tftp_server->fd, data_buffer, status);

                        /* If we did read some data. */
                        if (status > 0)
                        {
                            /* Update the data length. */
                            data_len += (uint32_t)status;

                            /* Push the read buffer on the buffer. */
                            status = fs_buffer_list_push(rx_buffer, data_buffer, (uint32_t)status, (FS_BUFFER_TAIL));
                        }
                        else
                        {
                            /* We must be at the end of the file. */
                            break;
                        }
                    }

                    /* Save the number of bytes we sent in this block. */
                    tftp_server->tx_block_len = (uint16_t)data_len;

                    /* If this was the last chunk. */
                    if (data_len != TFTP_BLOCK_SIZE)
                    {
                        /* We will be sending the last block. */
                        tftp_server->last_block = TRUE;
                    }
                }
            }

            /* If we are not dropping this frame. */
            else if (status != TFTP_FRAME_DROP)
            {
                /* If we have a session open for this client. */
                if ((tftp_server->fd != NULL) && (memcmp(&tftp_server->client_address, &tftp_server->port.last_datagram_address, sizeof(SOCKET_ADDRESS)) == 0))
                {
                    /* Close the file descriptor. */
                    fs_close(&tftp_server->fd);

                    /* Stop the timer. */
                    tftp_server->port_suspend.timeout = MAX_WAIT;
                    tftp_server->port_suspend.timeout_enabled  = FALSE;

                    SYS_LOG_FUNCTION_MSG(TFTPS, SYS_LOG_INFO, "file transfered interrupted", "");
                }

                /* Push the error opcode. */
                opcode = TFTP_OP_ERR;

                /* Push error response on the buffer. */
                if (fs_buffer_list_push_offset(rx_buffer, &opcode, 2, 0, (FS_BUFFER_PACKED | FS_BUFFER_TAIL)) == SUCCESS)
                {
                    switch (status)
                    {
                    /* If client is not connected or we received an out of
                     * bound frame. */
                    case TFTP_UNKNOWN_TID:
                    case TFTP_OUTOFBOUND_BLOCK:

                        /* Send transaction ID error. */
                        block = TFTP_ERROR_TID;

                        break;

                    /* Error is not mapped on the TFTP error. */
                    default:
                        /* Push the error code. */
                        block = TFTP_ERROR_GEN;
                        break;
                    }

                    /* Push error code on the buffer. */
                    if (fs_buffer_list_push(rx_buffer, &block, 2, (FS_BUFFER_PACKED | FS_BUFFER_TAIL)) == SUCCESS)
                    {
                        /* Push the required error message. */
                        switch (status)
                        {
                        /* TFTP command not supported. */
                        case TFTP_NOT_SUPPORTED:

                            /* Set error that opcode is not supported. */
                            status = fs_buffer_list_push(rx_buffer, TFTP_ERRMSG_NOT_SUPPORTED, sizeof(TFTP_ERRMSG_NOT_SUPPORTED), (FS_BUFFER_TAIL));

                            break;

                        /* Filename was too long. */
                        case TFTP_LONG_FILENAME:

                            /* Send error that file name is too long. */
                            status = fs_buffer_list_push(rx_buffer, TFTP_ERRMSG_FILENAME, sizeof(TFTP_ERRMSG_FILENAME), (FS_BUFFER_TAIL));

                            break;

                        /* Filename was not opened. */
                        case TFTP_ERROR_FS:

                            /* Send error that file system did not open the file. */
                            status = fs_buffer_list_push(rx_buffer, TFTP_ERRMSG_FS, sizeof(TFTP_ERRMSG_FS), (FS_BUFFER_TAIL));

                            break;

                        /* If no more clients can be connected. */
                        case TFTP_ERROR_EXHAUSTED:

                            /* Send error that connections are exhausted. */
                            status = fs_buffer_list_push(rx_buffer, TFTP_ERRMSG_EXHAUSTED, sizeof(TFTP_ERRMSG_EXHAUSTED), (FS_BUFFER_TAIL));

                            break;

                        /* If client is not connected. */
                        case TFTP_UNKNOWN_TID:

                            /* Send error that client's transaction ID was not resolved. */
                            status = fs_buffer_list_push(rx_buffer, TFTP_ERRMSG_TID, sizeof(TFTP_ERRMSG_TID), (FS_BUFFER_TAIL));

                            break;

                        /* Out of bound frame we received. */
                        case TFTP_OUTOFBOUND_BLOCK:

                            /* Send error that an out of bound block was received. */
                            status = fs_buffer_list_push(rx_buffer, TFTP_ERRMSG_BLOCK, sizeof(TFTP_ERRMSG_BLOCK), (FS_BUFFER_TAIL));

                            break;

                        /* Unknown error message. */
                        default:

                            /* Error message not known. */
                            status = fs_buffer_list_push(rx_buffer, "", 1, (FS_BUFFER_TAIL));

                            break;
                        }
                    }
                }
            }
        }

        /* If we are not sending a reply. */
        if (status != SUCCESS)
        {
            /* Free the buffer. */
            fs_buffer_add_list_list(rx_buffer, FS_LIST_FREE, FS_BUFFER_ACTIVE);
        }

        /* Release lock for buffer file descriptor. */
        fd_release_lock(rx_buffer->fd);

        if (status == SUCCESS)
        {
            /* Send this buffer back to the host. */
            tftp_server->port.destination_address = tftp_server->port.last_datagram_address;
            tftp_server->port.destination_address.local_ip = IPV4_ADDR_UNSPEC;
            ipv4_get_device_address(rx_buffer->fd, &tftp_server->port.destination_address.local_ip, NULL);

            /* Send received data back on the UDP port. */
            received = fs_write(&tftp_server->port, (uint8_t *)rx_buffer, sizeof(FS_BUFFER_LIST));
        }
    }

    SYS_LOG_FUNCTION_EXIT_STATUS(TFTPS, status);

} /* tftp_server_process */