Exemplo n.º 1
0
void ValueTinyint::setInt8Value(int8_t value)
{
    deleteValue();
    
    m_value = new int8_t( value );
    
    setValueLen(1);
}
Exemplo n.º 2
0
ValueLongBlock::ValueLongBlock( long_data_t long_data ): Value( 10 ), m_raw_data( 0 )
{
    setLongData( long_data );
    
    setValueLen( 0 );
    
    m_is_long_data = true;
}
Exemplo n.º 3
0
static void typeCompletion(const char *buf, size_t bufLength, linenoiseCompletions *lc, uint8_t actionCode,
                           const char *nodeString, size_t nodeStringLength, const char *keyString, size_t keyStringLength,
                           const char *partialTypeString, size_t partialTypeStringLength) {
    UNUSED_ARGUMENT(actionCode);

    uint8_t dataBuffer[1024];

    // Send request for all type names for this key on this node.
    dataBuffer[0] = GET_TYPES;
    dataBuffer[1] = 0; // UNUSED.
    setExtraLen(dataBuffer, 0); // UNUSED.
    setNodeLen(dataBuffer, (uint16_t) (nodeStringLength + 1)); // +1 for terminating NUL byte.
    setKeyLen(dataBuffer, (uint16_t) (keyStringLength + 1)); // +1 for terminating NUL byte.
    setValueLen(dataBuffer, 0); // UNUSED.

    memcpy(dataBuffer + 10, nodeString, nodeStringLength);
    dataBuffer[10 + nodeStringLength] = '\0';

    memcpy(dataBuffer + 10 + nodeStringLength + 1, keyString, keyStringLength);
    dataBuffer[10 + nodeStringLength + 1 + keyStringLength] = '\0';

    if (!sendUntilDone(sockFd, dataBuffer, 10 + nodeStringLength + 1 + keyStringLength + 1)) {
        // Failed to contact remote host, no auto-completion!
        return;
    }

    if (!recvUntilDone(sockFd, dataBuffer, 4)) {
        // Failed to contact remote host, no auto-completion!
        return;
    }

    // Decode response header fields (all in little-endian).
    uint8_t action = dataBuffer[0];
    uint8_t type = dataBuffer[1];
    uint16_t msgLength = le16toh(*(uint16_t * )(dataBuffer + 2));

    // Total length to get for response.
    if (!recvUntilDone(sockFd, dataBuffer + 4, msgLength)) {
        // Failed to contact remote host, no auto-completion!
        return;
    }

    if (action == ERROR || type != STRING) {
        // Invalid request made, no auto-completion.
        return;
    }

    // At this point we made a valid request and got back a full response.
    for (size_t i = 0; i < msgLength; i++) {
        if (strncasecmp((const char *) dataBuffer + 4 + i, partialTypeString, partialTypeStringLength) == 0) {
            linenoiseAddCompletionSuffix(lc, buf, bufLength - partialTypeStringLength,
                                         (const char *) dataBuffer + 4 + i, true, false);
        }

        // Jump to the NUL character after this string.
        i += strlen((const char *) dataBuffer + 4 + i);
    }
}
Exemplo n.º 4
0
ValueLongBlock::ValueLongBlock() : Value( 10 ), m_raw_data( 0 )
{
    setValueLen( 0 );
    
    m_is_long_data = true;
    
    m_long_data.raw_data = NULL;
    m_long_data.total_len = 0;
}
Exemplo n.º 5
0
void ValueTinyint::deleteValue()
{
    if (m_raw_data) delete [] m_raw_data;
    
    if (m_value)
    {
        delete (int8_t*) m_value;
        setValueLen(0);
    }
}
Exemplo n.º 6
0
void ValueLongBlock::setLongDataInfo(const long_data_info_t& long_data_info)
{
    deleteValue();
    
    m_value = new long_data_info_t;
    
    ( ( long_data_info_t* ) m_value )->page_id = long_data_info.page_id;
    ( ( long_data_info_t* ) m_value )->nr = long_data_info.nr;
    ( ( long_data_info_t* ) m_value )->total_len = long_data_info.total_len;
    
    if (long_data_info.total_len > 0)
    {
        setValueLen( 10 );
    }
    else 
    {
        setValueLen( 0 );
    }
    
}
Exemplo n.º 7
0
void ValueTinyint::setRawData(const uint8_t* data, uint16_t len)
{
    deleteValue();
    
    if ( len == 1 )
    {
        int8_t val = ( ( ( int32_t ) ( data[0] ) ) );
        
        setInt8Value(val);
    }
    else
    {
        setValueLen( 0 );
    }
}
Exemplo n.º 8
0
ValueTinyint::ValueTinyint() : ValueIncrementable( 1 ), m_raw_data( 0 )
{
    setType( TINYINT_TYPE );
    setValueLen( 0 );
}
Exemplo n.º 9
0
static void valueCompletion(const char *buf, size_t bufLength, linenoiseCompletions *lc, uint8_t actionCode,
                            const char *nodeString, size_t nodeStringLength, const char *keyString, size_t keyStringLength,
                            const char *typeString, size_t typeStringLength, const char *partialValueString, size_t partialValueStringLength) {
    UNUSED_ARGUMENT(actionCode);
    UNUSED_ARGUMENT(typeStringLength);

    enum sshs_node_attr_value_type type = sshsHelperStringToTypeConverter(typeString);
    if (type == UNKNOWN) {
        // Invalid type, no auto-completion.
        return;
    }

    if (partialValueStringLength != 0) {
        // If there already is content, we can't do any auto-completion here, as
        // we have no idea about what a valid value would be to complete ...
        // Unless this is a boolean, then we can propose true/false strings.
        if (type == BOOL) {
            if (strncmp("true", partialValueString, partialValueStringLength) == 0) {
                linenoiseAddCompletionSuffix(lc, buf, bufLength - partialValueStringLength, "true", false, false);
            }
            if (strncmp("false", partialValueString, partialValueStringLength) == 0) {
                linenoiseAddCompletionSuffix(lc, buf, bufLength - partialValueStringLength, "false", false, false);
            }
        }

        return;
    }

    uint8_t dataBuffer[1024];

    // Send request for the current value, so we can auto-complete with it as default.
    dataBuffer[0] = GET;
    dataBuffer[1] = (uint8_t) type;
    setExtraLen(dataBuffer, 0); // UNUSED.
    setNodeLen(dataBuffer, (uint16_t) (nodeStringLength + 1)); // +1 for terminating NUL byte.
    setKeyLen(dataBuffer, (uint16_t) (keyStringLength + 1)); // +1 for terminating NUL byte.
    setValueLen(dataBuffer, 0); // UNUSED.

    memcpy(dataBuffer + 10, nodeString, nodeStringLength);
    dataBuffer[10 + nodeStringLength] = '\0';

    memcpy(dataBuffer + 10 + nodeStringLength + 1, keyString, keyStringLength);
    dataBuffer[10 + nodeStringLength + 1 + keyStringLength] = '\0';

    if (!sendUntilDone(sockFd, dataBuffer, 10 + nodeStringLength + 1 + keyStringLength + 1)) {
        // Failed to contact remote host, no auto-completion!
        return;
    }

    if (!recvUntilDone(sockFd, dataBuffer, 4)) {
        // Failed to contact remote host, no auto-completion!
        return;
    }

    // Decode response header fields (all in little-endian).
    uint8_t action = dataBuffer[0];
    uint16_t msgLength = le16toh(*(uint16_t * )(dataBuffer + 2));

    // Total length to get for response.
    if (!recvUntilDone(sockFd, dataBuffer + 4, msgLength)) {
        // Failed to contact remote host, no auto-completion!
        return;
    }

    if (action == ERROR) {
        // Invalid request made, no auto-completion.
        return;
    }

    // At this point we made a valid request and got back a full response.
    // We can just use it directly and paste it in as completion.
    linenoiseAddCompletionSuffix(lc, buf, bufLength, (const char *) dataBuffer + 4, false, false);

    // If this is a boolean value, we can also add the inverse as a second completion.
    if (type == BOOL) {
        if (strcmp((const char *) dataBuffer + 4, "true") == 0) {
            linenoiseAddCompletionSuffix(lc, buf, bufLength, "false", false, false);
        }
        else {
            linenoiseAddCompletionSuffix(lc, buf, bufLength, "true", false, false);
        }
    }
}
Exemplo n.º 10
0
static void nodeCompletion(const char *buf, size_t bufLength, linenoiseCompletions *lc, uint8_t actionCode,
                           const char *partialNodeString, size_t partialNodeStringLength) {
    UNUSED_ARGUMENT(actionCode);

    // If partialNodeString is still empty, the first thing is to complete the root.
    if (partialNodeStringLength == 0) {
        linenoiseAddCompletionSuffix(lc, buf, bufLength, "/", false, false);
        return;
    }

    // Get all the children of the last fully defined node (/ or /../../).
    char *lastNode = strrchr(partialNodeString, '/');
    if (lastNode == NULL) {
        // No / found, invalid, cannot auto-complete.
        return;
    }

    size_t lastNodeLength = (size_t) (lastNode - partialNodeString) + 1;

    uint8_t dataBuffer[1024];

    // Send request for all children names.
    dataBuffer[0] = GET_CHILDREN;
    dataBuffer[1] = 0; // UNUSED.
    setExtraLen(dataBuffer, 0); // UNUSED.
    setNodeLen(dataBuffer, (uint16_t) (lastNodeLength + 1)); // +1 for terminating NUL byte.
    setKeyLen(dataBuffer, 0); // UNUSED.
    setValueLen(dataBuffer, 0); // UNUSED.

    memcpy(dataBuffer + 10, partialNodeString, lastNodeLength);
    dataBuffer[10 + lastNodeLength] = '\0';

    if (!sendUntilDone(sockFd, dataBuffer, 10 + lastNodeLength + 1)) {
        // Failed to contact remote host, no auto-completion!
        return;
    }

    if (!recvUntilDone(sockFd, dataBuffer, 4)) {
        // Failed to contact remote host, no auto-completion!
        return;
    }

    // Decode response header fields (all in little-endian).
    uint8_t action = dataBuffer[0];
    uint8_t type = dataBuffer[1];
    uint16_t msgLength = le16toh(*(uint16_t * )(dataBuffer + 2));

    // Total length to get for response.
    if (!recvUntilDone(sockFd, dataBuffer + 4, msgLength)) {
        // Failed to contact remote host, no auto-completion!
        return;
    }

    if (action == ERROR || type != STRING) {
        // Invalid request made, no auto-completion.
        return;
    }

    // At this point we made a valid request and got back a full response.
    for (size_t i = 0; i < msgLength; i++) {
        if (strncasecmp((const char *) dataBuffer + 4 + i, lastNode + 1, strlen(lastNode + 1)) == 0) {
            linenoiseAddCompletionSuffix(lc, buf, bufLength - strlen(lastNode + 1), (const char *) dataBuffer + 4 + i,
                                         false, true);
        }

        // Jump to the NUL character after this string.
        i += strlen((const char *) dataBuffer + 4 + i);
    }
}
Exemplo n.º 11
0
static void handleInputLine(const char *buf, size_t bufLength) {
    // First let's split up the command into its constituents.
    char *commandParts[MAX_CMD_PARTS + 1] = { NULL };

    // Create a copy of buf, so that strtok_r() can modify it.
    char bufCopy[bufLength + 1];
    strcpy(bufCopy, buf);

    // Split string into usable parts.
    size_t idx = 0;
    char *tokenSavePtr = NULL, *nextCmdPart = NULL, *currCmdPart = bufCopy;
    while ((nextCmdPart = strtok_r(currCmdPart, " ", &tokenSavePtr)) != NULL) {
        if (idx < MAX_CMD_PARTS) {
            commandParts[idx] = nextCmdPart;
        }
        else {
            // Abort, too many parts.
            fprintf(stderr, "Error: command is made up of too many parts.\n");
            return;
        }

        idx++;
        currCmdPart = NULL;
    }

    // Check that we got something.
    if (commandParts[CMD_PART_ACTION] == NULL) {
        fprintf(stderr, "Error: empty command.\n");
        return;
    }

    // Let's get the action code first thing.
    uint8_t actionCode = UINT8_MAX;

    for (size_t i = 0; i < actionsLength; i++) {
        if (strcmp(commandParts[CMD_PART_ACTION], actions[i].name) == 0) {
            actionCode = actions[i].code;
        }
    }

    // Control message format: 1 byte ACTION, 1 byte TYPE, 2 bytes EXTRA_LEN,
    // 2 bytes NODE_LEN, 2 bytes KEY_LEN, 2 bytes VALUE_LEN, then up to 4086
    // bytes split between EXTRA, NODE, KEY, VALUE (with 4 bytes for NUL).
    // Basically: (EXTRA_LEN + NODE_LEN + KEY_LEN + VALUE_LEN) <= 4086.
    // EXTRA, NODE, KEY, VALUE have to be NUL terminated, and their length
    // must include the NUL termination byte.
    // This results in a maximum message size of 4096 bytes (4KB).
    uint8_t dataBuffer[4096];
    size_t dataBufferLength = 0;

    // Now that we know what we want to do, let's decode the command line.
    switch (actionCode) {
    case NODE_EXISTS: {
        // Check parameters needed for operation.
        if (commandParts[CMD_PART_NODE] == NULL) {
            fprintf(stderr, "Error: missing node parameter.\n");
            return;
        }
        if (commandParts[CMD_PART_NODE + 1] != NULL) {
            fprintf(stderr, "Error: too many parameters for command.\n");
            return;
        }

        size_t nodeLength = strlen(commandParts[CMD_PART_NODE]) + 1; // +1 for terminating NUL byte.

        dataBuffer[0] = actionCode;
        dataBuffer[1] = 0; // UNUSED.
        setExtraLen(dataBuffer, 0); // UNUSED.
        setNodeLen(dataBuffer, (uint16_t) nodeLength);
        setKeyLen(dataBuffer, 0); // UNUSED.
        setValueLen(dataBuffer, 0); // UNUSED.

        memcpy(dataBuffer + 10, commandParts[CMD_PART_NODE], nodeLength);

        dataBufferLength = 10 + nodeLength;

        break;
    }

    case ATTR_EXISTS:
    case GET: {
        // Check parameters needed for operation.
        if (commandParts[CMD_PART_NODE] == NULL) {
            fprintf(stderr, "Error: missing node parameter.\n");
            return;
        }
        if (commandParts[CMD_PART_KEY] == NULL) {
            fprintf(stderr, "Error: missing key parameter.\n");
            return;
        }
        if (commandParts[CMD_PART_TYPE] == NULL) {
            fprintf(stderr, "Error: missing type parameter.\n");
            return;
        }
        if (commandParts[CMD_PART_TYPE + 1] != NULL) {
            fprintf(stderr, "Error: too many parameters for command.\n");
            return;
        }

        size_t nodeLength = strlen(commandParts[CMD_PART_NODE]) + 1; // +1 for terminating NUL byte.
        size_t keyLength = strlen(commandParts[CMD_PART_KEY]) + 1; // +1 for terminating NUL byte.

        enum sshs_node_attr_value_type type = sshsHelperStringToTypeConverter(commandParts[CMD_PART_TYPE]);
        if (type == UNKNOWN) {
            fprintf(stderr, "Error: invalid type parameter.\n");
            return;
        }

        dataBuffer[0] = actionCode;
        dataBuffer[1] = (uint8_t) type;
        setExtraLen(dataBuffer, 0); // UNUSED.
        setNodeLen(dataBuffer, (uint16_t) nodeLength);
        setKeyLen(dataBuffer, (uint16_t) keyLength);
        setValueLen(dataBuffer, 0); // UNUSED.

        memcpy(dataBuffer + 10, commandParts[CMD_PART_NODE], nodeLength);
        memcpy(dataBuffer + 10 + nodeLength, commandParts[CMD_PART_KEY], keyLength);

        dataBufferLength = 10 + nodeLength + keyLength;

        break;
    }

    case PUT: {
        // Check parameters needed for operation.
        if (commandParts[CMD_PART_NODE] == NULL) {
            fprintf(stderr, "Error: missing node parameter.\n");
            return;
        }
        if (commandParts[CMD_PART_KEY] == NULL) {
            fprintf(stderr, "Error: missing key parameter.\n");
            return;
        }
        if (commandParts[CMD_PART_TYPE] == NULL) {
            fprintf(stderr, "Error: missing type parameter.\n");
            return;
        }
        if (commandParts[CMD_PART_VALUE] == NULL) {
            fprintf(stderr, "Error: missing value parameter.\n");
            return;
        }
        if (commandParts[CMD_PART_VALUE + 1] != NULL) {
            fprintf(stderr, "Error: too many parameters for command.\n");
            return;
        }

        size_t nodeLength = strlen(commandParts[CMD_PART_NODE]) + 1; // +1 for terminating NUL byte.
        size_t keyLength = strlen(commandParts[CMD_PART_KEY]) + 1; // +1 for terminating NUL byte.
        size_t valueLength = strlen(commandParts[CMD_PART_VALUE]) + 1; // +1 for terminating NUL byte.

        enum sshs_node_attr_value_type type = sshsHelperStringToTypeConverter(commandParts[CMD_PART_TYPE]);
        if (type == UNKNOWN) {
            fprintf(stderr, "Error: invalid type parameter.\n");
            return;
        }

        dataBuffer[0] = actionCode;
        dataBuffer[1] = (uint8_t) type;
        setExtraLen(dataBuffer, 0); // UNUSED.
        setNodeLen(dataBuffer, (uint16_t) nodeLength);
        setKeyLen(dataBuffer, (uint16_t) keyLength);
        setValueLen(dataBuffer, (uint16_t) valueLength);

        memcpy(dataBuffer + 10, commandParts[CMD_PART_NODE], nodeLength);
        memcpy(dataBuffer + 10 + nodeLength, commandParts[CMD_PART_KEY], keyLength);
        memcpy(dataBuffer + 10 + nodeLength + keyLength, commandParts[CMD_PART_VALUE], valueLength);

        dataBufferLength = 10 + nodeLength + keyLength + valueLength;

        break;
    }

    default:
        fprintf(stderr, "Error: unknown command.\n");
        return;
    }

    // Send formatted command to configuration server.
    if (!sendUntilDone(sockFd, dataBuffer, dataBufferLength)) {
        fprintf(stderr, "Error: unable to send data to config server (%d).\n", errno);
        return;
    }

    // The response from the server follows a simplified version of the request
    // protocol. A byte for ACTION, a byte for TYPE, 2 bytes for MSG_LEN and then
    // up to 4092 bytes of MSG, for a maximum total of 4096 bytes again.
    // MSG must be NUL terminated, and the NUL byte shall be part of the length.
    if (!recvUntilDone(sockFd, dataBuffer, 4)) {
        fprintf(stderr, "Error: unable to receive data from config server (%d).\n", errno);
        return;
    }

    // Decode response header fields (all in little-endian).
    uint8_t action = dataBuffer[0];
    uint8_t type = dataBuffer[1];
    uint16_t msgLength = le16toh(*(uint16_t * )(dataBuffer + 2));

    // Total length to get for response.
    if (!recvUntilDone(sockFd, dataBuffer + 4, msgLength)) {
        fprintf(stderr, "Error: unable to receive data from config server (%d).\n", errno);
        return;
    }

    // Convert action back to a string.
    const char *actionString = NULL;

    // Detect error response.
    if (action == ERROR) {
        actionString = "error";
    }
    else {
        for (size_t i = 0; i < actionsLength; i++) {
            if (actions[i].code == action) {
                actionString = actions[i].name;
            }
        }
    }

    // Display results.
    printf("Result: action=%s, type=%s, msgLength=%" PRIu16 ", msg='%s'.\n", actionString,
           sshsHelperTypeToStringConverter(type), msgLength, dataBuffer + 4);
}