Exemplo n.º 1
0
/**
 * Converts the onion-id field in the PDU to a string and sets the
 * address of the given value parameter to this string.
 * @param pdu Pointer to PDU structure
 * @param value Double pointer to string
 * @return 1 field was not set in pdu structure, 0 on success (string must be freed),
 * -1 in case of error (e.g. illegal value in pdu structure , ...)
 */
int
oni_pdu_to_str(dchat_pdu_t* pdu, char** value)
{
    // no onion-id has been set
    if (pdu->onion_id[0] == '\0')
    {
        return 1;
    }

    // check if set onion id is valid
    if (!is_valid_onion(pdu->onion_id))
    {
        return -1;
    }

    //copy onion id
    *value = malloc(strlen(pdu->onion_id) + 1);

    if (*value == NULL)
    {
        ui_fatal("Memory allocation for onion-id failed!");
    }

    *value[0] = '\0';
    strcat(*value, pdu->onion_id);
    return 0;
}
Exemplo n.º 2
0
/**
 * Converts the listening-port field in the PDU to a string and sets the
 * address of the given value parameter to this string.
 * @param pdu Pointer to PDU structure
 * @param value Double pointer to string
 * @return 1 field was not set in pdu structure, 0 on success (string must be freed),
 * -1 in case of error (e.g. illegal value in pdu structure , ...)
 */
int
lnp_pdu_to_str(dchat_pdu_t* pdu, char** value)
{
    // listening port has not been specified
    if (pdu->lport == 0)
    {
        return 1;
    }

    // check if listening port is valid
    if (!is_valid_port(pdu->lport))
    {
        return -1;
    }

    *value = malloc(MAX_INT_STR + 1);

    if (*value == NULL)
    {
        ui_fatal("Memory allocation for listening-port failed!");
    }

    snprintf(*value, MAX_INT_STR, "%d", pdu->lport);
    return 0;
}
Exemplo n.º 3
0
/**
 * Converts the version field in the PDU to a string and sets the address of the given
 * value parameter to this string.
 * @param pdu Pointer to PDU structure
 * @param value Double pointer to string
 * @return 1 field was not set in pdu structure, 0 on success (string must be freed),
 * -1 in case of error (e.g. illegal value in pdu structure , ...)
 */
int
ver_pdu_to_str(dchat_pdu_t* pdu, char** value)
{
    char* version = "1.0";

    // nothing has been set
    if (pdu->version == 0)
    {
        return 1;
    }

    // if version is V1
    if (pdu->version == DCHAT_V1)
    {
        *value = malloc(strlen(version) + 1);

        if (*value == NULL)
        {
            ui_fatal("Memory allocation for version failed!");
        }

        *value[0] = '\0';
        strcat(*value, version);
        return 0;
    }

    return -1;
}
Exemplo n.º 4
0
/**
 * Converts the nickname field in the PDU to a string and sets the
 * address of the given value parameter to this string.
 * @param pdu Pointer to PDU structure
 * @param value Double pointer to string
 * @return 1 field was not set in pdu structure, 0 on success (string must be freed),
 * -1 in case of error (e.g. illegal value in pdu structure , ...)
 */
int
nic_pdu_to_str(dchat_pdu_t* pdu, char** value)
{
    if (pdu->nickname[0] == '\0')
    {
        return 1;
    }

    if (!is_valid_nickname(pdu->nickname))
    {
        return -1;
    }

    //copy nickname
    *value = malloc(strlen(pdu->nickname) + 1);

    if (*value == NULL)
    {
        ui_fatal("Memory allocation for nickname failed!");
    }

    *value[0] = '\0';
    strcat(*value, pdu->nickname);
    return 0;
}
Exemplo n.º 5
0
bool ui_poll_break() {
  ui_display_led();
  if (BREAK) return true;
  char c = myraw(false);
  if (c == 0) return false;
  ui_fatal(F(" User BREAK. "));
  return true;
}
Exemplo n.º 6
0
/**
 * Initializes the content of a DChat PDU with the given value.
 * @param pdu     Pointer to PDU whose content will be initialized
 * @param content Pointer to content
 * @param         len Lenght of content
 */
void
init_dchat_pdu_content(dchat_pdu_t* pdu, char* content, int len)
{
    if ((pdu->content = malloc(len)) == NULL)
    {
        ui_fatal("Memory allocation for PDU content failed!");
    }

    memcpy(pdu->content, content, len);
    pdu->content_length = len;
}
Exemplo n.º 7
0
void data_dec() {

  if (jh_index  <= 0) {
    ui_fatal(F(" CLOCK is before start of table "));
    return;
  }

  jh_index--;
  jh_next = jh_prev;
  jh_prev = jh_next - get_djh();
}
Exemplo n.º 8
0
/**
 * Parses the given value to a server field and sets its value,
 * if valid, in the given PDU structure.
 * @param value String to parse
 * @param pdu Pointer to PDU structure
 * @return 0 if value is a valid server string, -1 otherwise
 */
int
srv_str_to_pdu(char* value, dchat_pdu_t* pdu)
{
    if ((pdu->server = malloc(strlen(value) + 1)) == NULL)
    {
        ui_fatal("Memory allocation for server failed!");
    }

    pdu->server[0] = '\0';
    strcat(pdu->server, value);
    return 0;
}
Exemplo n.º 9
0
void data_inc() {

  if ( jh_index  >=  (n_djh - 1) ) {
    ui_fatal(F(" CLOCK is after end of table "));
    return;
  }

  jh_index++;
  jh_prev = jh_next;
  jh_next = jh_prev + get_djh();

}
Exemplo n.º 10
0
/**
 * Converts the content-length field in the PDU to a string and sets the
 * address of the given value parameter to this string.
 * @param pdu Pointer to PDU structure
 * @param value Double pointer to string
 * @return 1 field was not set in pdu structure, 0 on success (string must be freed),
 * -1 in case of error (e.g. illegal value in pdu structure , ...)
 */
int
ctl_pdu_to_str(dchat_pdu_t* pdu, char** value)
{
    // check if content-length is valid
    if (!is_valid_content_length(pdu->content_length))
    {
        return -1;
    }

    *value = malloc(MAX_INT_STR + 1);

    if (*value == NULL)
    {
        ui_fatal("Memory allocation for content-length failed!");
    }

    snprintf(*value, MAX_INT_STR, "%d", pdu->content_length);
    return 0;
}
Exemplo n.º 11
0
/**
 * Converts the server field in the PDU to a string and sets the
 * address of the given value parameter to this string.
 * @param pdu Pointer to PDU structure
 * @param value Double pointer to string
 * @return 1 field was not set in pdu structure, 0 on success (string must be freed),
 * -1 in case of error (e.g. illegal value in pdu structure , ...)
 */
int
srv_pdu_to_str(dchat_pdu_t* pdu, char** value)
{
    if (pdu->server == NULL)
    {
        return 1;
    }

    *value = malloc(strlen(pdu->server) + 1);

    if (*value == NULL)
    {
        ui_fatal("Memory allocation for date failed!");
    }

    *value[0] = '\0';
    strcat(*value, pdu->server);
    return 0;
}
Exemplo n.º 12
0
/**
 *  Read a line terminated with \\n from a file descriptor.
 *  Reads a line from the given file descriptor until \\n is found.
 *  @param line Double pointer used for dynamic memory allocation since
 *              characters will be stored on the heap.
 *  @return: length of bytes read, 0 on EOF, -1 on error
 */
int
read_line(int fd, char** line)
{
    char* ptr;             // line pointer
    char* alc_ptr = NULL;  // used for realloc
    int len = 1;           // current length of string (at least 1 char)
    int ret;               // return value
    *line = NULL;

    do
    {
        // allocate memory for new character
        alc_ptr = realloc(*line, len + 1);

        if (alc_ptr == NULL)
        {
            if (*line != NULL)
            {
                free(*line);
            }

            ui_fatal("Reallocation of input string failed!");
        }

        *line = alc_ptr;
        ptr = *line + len - 1;
        len++;
    }
    while ((ret = read(fd, ptr, 1)) > 0 && *ptr != '\n');

    // on error or EOF of read
    if (ret <= 0)
    {
        free(*line);
        return ret;
    }

    // terminate string
    *(ptr + 1) = '\0';
    return len - 1; // length of string excluding \0
}
Exemplo n.º 13
0
/**
 * Converts the content-type field in the PDU to a string and sets the
 * address of the given value parameter to this string.
 * @param pdu Pointer to PDU structure
 * @param value Double pointer to string
 * @return 1 field was not set in pdu structure, 0 on success (string must be freed),
 * -1 in case of error (e.g. illegal value in pdu structure , ...)
 */
int
ctt_pdu_to_str(dchat_pdu_t* pdu, char** value)
{
    dchat_content_types_t content_types;
    char* type;

    // content type has not been set
    if (pdu->content_type == 0)
    {
        return 1;
    }

    // init available content types
    if (init_dchat_content_types(&content_types) == -1)
    {
        return -1;
    }

    // iterate through content-types and build a content type string
    for (int i = 0; i < CTT_AMOUNT; i++)
    {
        if (content_types.type[i].ctt_id == pdu->content_type)
        {
            type = content_types.type[i].ctt_name;
            *value = malloc(strlen(type) + 1);

            if (*value == NULL)
            {
                ui_fatal("Memory allocation for content-type failed!");
            }

            *value[0] = '\0';
            strncat(*value, type, strlen(type));
            return 0;
        }
    }

    return -1;
}
Exemplo n.º 14
0
/**
 * Converts the sent field in the PDU to a string and sets the
 * address of the given value parameter to this string.
 * @param pdu Pointer to PDU structure
 * @param value Double pointer to string
 * @return 1 field was not set in pdu structure, 0 on success (string must be freed),
 * -1 in case of error (e.g. illegal value in pdu structure , ...)
 */
int
dat_pdu_to_str(dchat_pdu_t* pdu, char** value)
{
    int max_len = 100;

    // check if date field is empty
    if (iszero(&pdu->sent, sizeof(pdu->sent)))
    {
        return 1;
    }

    *value = malloc(max_len);

    if (*value == NULL)
    {
        ui_fatal("Memory allocation for date failed!");
    }

    *value[0] = '\0';
    strftime(*value, max_len, "%a, %d %b %Y %H:%M:%S GMT", &pdu->sent);
    return 0;
}
Exemplo n.º 15
0
/**
 *  Extracts a fraction of the content.
 *  Part of the content of a PDU will be extracted beginning at offset and
 *  ending at the given terminating character term. The partial content, given
 *  as double pointer should be freed after the successfull call of this function.
 *  @param pdu      Pointer to a pdu containing the content
 *  @param offset   Offset where the extraction will begin
 *  @param term     Terminating character where the extraction will end
 *  @param content  Extracted content
 *  @return Returns offset where the terminating character has
 *          been found in the content of the pdu, -1 on error
 */
int
get_content_part(dchat_pdu_t* pdu, int offset, char term, char** content)
{
    int line_end; // detected end of line, represented as index
    char* ptr;    // content pointer

    // check if offset is within the content
    if (offset >= pdu->content_length)
    {
        ui_log(LOG_ERR, "Could not extract partial content!");
        return -1;
    }

    // determine line end -> \n or end of content
    for (ptr = (pdu->content + offset), line_end = offset; *ptr != term &&
         line_end < pdu->content_length; ptr++, line_end++);

    // if end of content is reached before \n
    if (line_end == pdu->content_length && *(ptr - 1) != term)
    {
        ui_log(LOG_ERR, "Could not extract partial content!");
        return -1;
    }

    // reserve enough space for line + \0
    *content = malloc(line_end + 2); // +1 since its an index and +1 for \0

    if (*content == NULL)
    {
        ui_fatal("Memory allocation for partial content failed!");
    }

    // copy data into line buffer
    strncpy(*content, &pdu->content[offset], (line_end - offset + 1));
    (*content)[line_end + 1] = '\0';
    return line_end;
}
Exemplo n.º 16
0
/**
 * Initializes a DChat PDU with the given values.
 * @param pdu          Pointer to PDU structure whose members will be initialized
 * @param version      Version of DChat Protocol
 * @param content_type Content-Type
 * @param onion_id     Onion-ID
 * @param lport        Listening port
 * @param nickname     Nickname
 */
int
init_dchat_pdu(dchat_pdu_t* pdu, float version, int content_type,
               char* onion_id, int lport,
               char* nickname)
{
    if (!is_valid_version(version))
    {
        ui_log(LOG_WARN, "Invalid version '%2.1f'!", version);
        return -1;
    }

    if (!is_valid_content_type(content_type))
    {
        ui_log(LOG_WARN, "Invalid Content-Type '0x%02x'!", content_type);
        return -1;
    }

    if (!is_valid_onion(onion_id))
    {
        ui_log(LOG_WARN, "Invalid Onion-ID '%s'!", onion_id);
        return -1;
    }

    if (!is_valid_port(lport))
    {
        ui_log(LOG_WARN, "Invalid Listening-Port '%d'!", lport);
        return -1;
    }

    if (!is_valid_nickname(nickname))
    {
        ui_log(LOG_WARN, "Invalid Nickname '%s'!", nickname);
        return -1;
    }

    memset(pdu, 0, sizeof(*pdu));
    // set dchat version
    pdu->version      = version;
    // set content-type
    pdu->content_type = content_type;
    // set hostname
    pdu->onion_id[0]  = '\0';
    strncpy(pdu->onion_id, onion_id, ONION_ADDRLEN);
    // set listening port
    pdu->lport        = lport;
    // set nickname
    pdu->nickname[0]  = '\0';
    strncpy(pdu->nickname, nickname, MAX_NICKNAME);
    // set initialization datetime
    time_t now        = time(0);
    struct tm tm      = *gmtime(&now);
    memcpy(&pdu->sent, &tm, sizeof(struct tm));
    // set servername
    char* package_name = PACKAGE_NAME;
    char* package_version = PACKAGE_VERSION;
    pdu->server = malloc(strlen(package_name)+strlen(package_version)+2);

    if (pdu->server == NULL)
    {
        ui_fatal("Memory allocation for server failed!");
    }

    pdu->server[0] = '\0';
    strcat(pdu->server, package_name);
    strcat(pdu->server, "/");
    strcat(pdu->server, package_version);
    return 0;
}
Exemplo n.º 17
0
/**
 *  Crafts a DChat header string.
 *  Crafts a header string according to the given header_id (see: dchat_encoder.h) together
 *  with the header information stored in the PDU structure.
 *  @param pdu       Pointer to a message structure that holds header information like
 *                   Content-Type, Content-Length, ...
 *  @param header_id Defines for which header a string should be crafted (Content-Type, ...)
 *  @return  Pointer to a header string (stored on heap -> must be freed) or NULL on error
 *           This string is not terminated with \\n or \\r\\n respectively
 */
int
encode_header(dchat_pdu_t* pdu, int header_id, char** headerline)
{
    dchat_v1_t proto;    // DChat V1 headers
    char* header = NULL; // header key string
    char* value  = NULL; // header value string
    int len;             // length of string in total
    int ret;

    if (init_dchat_v1(&proto) == -1)
    {
        return -1;
    }

    // iterate through supported headers
    for (int i = 0; i < HDR_AMOUNT; i++)
    {
        if (proto.header[i].header_id == header_id)
        {
            header = proto.header[i].header_name;
            len = strlen(header);

            if ((ret = proto.header[i].pdu_to_str(pdu, &value)) == -1)
            {
                return -1;
            }

            // check if header is mandatory, if no value has been set
            // in the pdu structure
            if (ret == 1)
            {
                // if header is mandatory -> raise error
                // otherwise just return and do nothing
                if (proto.header[i].mandatory)
                {
                    return -1;
                }

                return 1;
            }

            len += strlen(value);
            len += 4; // add three bytes for ':', a " ", '\n' and '\0';

            // allocate memory for header string
            if ((*headerline = malloc(len)) == NULL)
            {
                ui_fatal("Memory allocation for header-value string failed!");
            }

            // assemble header string
            *headerline[0] = '\0';
            strncat(*headerline, header, strlen(header));
            strncat(*headerline, ":", 1); // seperate key from value -> "key:value"
            strncat(*headerline, " ", 1); // add a " " after the semicolon -> "key: value"
            strncat(*headerline, value, strlen(value)); // add value
            strncat(*headerline, "\n", 1);
            // free converted pdu structure value
            free(value);
            return 0;
        }
    }

    return -1;
}
Exemplo n.º 18
0
/**
 * Converts a PDU to a string that will be written to a file descriptor.
 * Converts the given PDU to string which then will be written to the given file descriptor.
 * First the headers of the PDU will be written, then an empty line and at last the content.
 * (See specification of the dchat protocol)
 * @param fd  File descriptor where the dchat PDU will be written to
 * @param pdu Pointer to a PDU structure holding the header and content data
 * @return Amount of bytes of content that that have been written. This should be equal
 *         to the value defined in the attribute "content_length" of the given PDU structure
 *         or -1 in case of error
 */
int
write_pdu(int fd, dchat_pdu_t* pdu)
{
    dchat_v1_t proto;                //Available DChat headers
    char* header;                    //DChat header
    char* pdu_raw;                   //Final PDU
    int ret;                         //Return value
    int pdulen=1;                    //Total length of PDU

    if (init_dchat_v1(&proto) == -1)
    {
        return -1;
    }

    // get version header string
    if ((ret = encode_header(pdu, HDR_ID_VER, &header)) == -1 || ret == 1)
    {
        return -1;
    }

    pdulen += strlen(header);

    if ((pdu_raw = malloc(pdulen)) == NULL)
    {
        ui_fatal("Memory allocation for pdu failed!");
    }

    // copy version header to raw pdu
    pdu_raw[0] = '\0';
    strcat(pdu_raw, header);
    free(header);

    // iterate through supported headers
    for (int i = 0; i < HDR_AMOUNT; i++)
    {
        // get header strings except version header, if set in pdu structure
        if (proto.header[i].header_id != HDR_ID_VER)
        {
            // get header string
            if ((ret = encode_header(pdu, proto.header[i].header_id, &header)) == -1)
            {
                free(pdu_raw);
                return -1;
            }

            // if header was mandatory, but value was not set in pdu structure
            // raise an error
            if (ret == 1)
            {
                if (proto.header[i].mandatory)
                {
                    free(pdu_raw);
                    return -1;
                }

                continue;
            }

            // (re)allocate memory for new header (excluding \0)
            pdulen += strlen(header);
            pdu_raw = realloc(pdu_raw, pdulen);

            if (pdu_raw == NULL)
            {
                ui_fatal("Reallocation of pdu failed!");
            }

            // copy header to pdu
            strcat(pdu_raw, header);
            free(header);
        }
    }

    // (re)allocate memory for empty line and content
    pdulen += pdu->content_length + 1;
    pdu_raw = realloc(pdu_raw, pdulen);

    if (pdu_raw == NULL)
    {
        ui_fatal("Reallocation of pdu failed!");
    }

    // add empty line
    strcat(pdu_raw, "\n");
    // add content
    strncat(pdu_raw, pdu->content, pdu->content_length);
    // exclude \0
    pdulen--;
    //write pdu to file descriptor
    ret = write(fd, pdu_raw, strlen(pdu_raw));
    free(pdu_raw);
    return pdulen;
}
Exemplo n.º 19
0
/**
 *  Decodes a string into a DChat header.
 *  Attempts to decode the given \\n terminated line and sets
 *  corresponding header attributes in the given pdu.
 *  @param pdu  Pointer to PDU structure where header attributes
 *  will be set
 *  @param line Line to parse for dchat-headers; must be \\n terminated
 *  @return 0 if line is a dchat header, -1 otherwise
 */
int
decode_header(dchat_pdu_t* pdu, char* line)
{
    char* temp;
    char* key;          // header key (e.g. Content-Type)
    char* value;        // header value (e.g. text/plain)
    char* delim = ":";  // delimiter char
    char* save_ptr;     // used for strtok
    int len;            // length of value
    int end;            // index of termination chars (\r)\n of value
    int ret;            // return of parsed value
    dchat_v1_t proto;   // DChat V1 headers

    if (line == NULL)
    {
        return -1;
    }

    // copy line to work with
    temp = malloc(strlen(line) + 1);

    if (temp == NULL)
    {
        ui_fatal("Memory allocation for temporary decoder line failed!");
    }

    temp[0] = '\0';
    strcat(temp, line);

    // split line: header format -> key:value
    if ((key = strtok_r(temp, delim, &save_ptr)) == NULL)
    {
        free(temp);
        return -1;
    }
    else if ((value = strtok_r(NULL, delim, &save_ptr)) == NULL)
    {
        free(temp);
        return -1;
    }

    // only split the very first token from temp, to keep
    // the value one token (containing possible delim chars)
    if (save_ptr != NULL)
    {
        value[strlen(value)] = *delim;
    }

    // first character must be a whitespace
    if (strncmp(value, " ", 1) != 0)
    {
        free(temp);
        return -1;
    }

    // skip " "
    value++;

    if ((ret = is_valid_termination(value)) == -1)
    {
        free(temp);
        return -1;
    }

    // remove termination characters
    value[ret] = '\0';

    if (init_dchat_v1(&proto) == -1)
    {
        free(temp);
        return -1;
    }

    // iterate through headers and check if value is valid
    // if valid parse value and set attributes in the PDU
    for (int i = 0; i < HDR_AMOUNT; i++)
    {
        if (!strcmp(key, proto.header[i].header_name))
        {
            ret = proto.header[i].str_to_pdu(value, pdu);
            free(temp);
            return ret;
        }
    }

    free(temp);
    return -1;
}