<commit_before>/**
 * Copyright (c) 2014 NetEase, Inc. and other Pomelo contributors
 * MIT Licensed.
 */

#include <assert.h>
#include <string.h>
#include <stdint.h>
#include <jansson.h>

#include <pc_lib.h>

#include "pr_msg.h"
#include "tr_uv_tcp_i.h"

#define PC_MSG_FLAG_BYTES 1
#define PC_MSG_ROUTE_LEN_BYTES 1
#define PC_MSG_ROUTE_CODE_BYTES 2

#define PC_MSG_HAS_ID(TYPE) ((TYPE) == PC_MSG_REQUEST ||                      \
        (TYPE) == PC_MSG_RESPONSE)

#define PC_MSG_HAS_ROUTE(TYPE) ((TYPE) != PC_MSG_RESPONSE)

#define PC_MSG_VALIDATE(TYPE) ((TYPE) == PC_MSG_REQUEST ||                    \
        (TYPE) == PC_MSG_NOTIFY ||                                            \
        (TYPE) == PC_MSG_RESPONSE ||                                          \
        (TYPE) == PC_MSG_PUSH)

/**
 * message type.
 */
typedef enum {
    PC_MSG_REQUEST = 0,
    PC_MSG_NOTIFY,
    PC_MSG_RESPONSE,
    PC_MSG_PUSH
} pc_msg_type;

typedef struct {
    uint32_t id;
    pc_msg_type type;
    uint8_t compressRoute;
    union {
        uint16_t route_code;
        const char *route_str;
    } route;
    pc_buf_t body;
} pc__msg_raw_t;

static PC_INLINE const char *pc__resolve_dictionary(const json_t* code2route, uint16_t code)
{
    char code_str[16];
    memset(code_str, 0, 16);
    sprintf(code_str, "%u", code);
    return json_string_value(json_object_get(code2route, code_str));
}

#define PC__MSG_CHECK_LEN(INDEX, LENGTH)                                      \
do {                                                                          \
    if((INDEX) > (LENGTH)) {                                                  \
        pc_lib_log(PC_LOG_ERROR, "pc_msg_decode_to_raw - invalid length");    \
        goto error;                                                           \
    }                                                                         \
} while(0)


static pc__msg_raw_t *pc_msg_decode_to_raw(const pc_buf_t* buf) 
{
    const char* data = buf->base;
    size_t len = buf->len;
    pc__msg_raw_t *msg = NULL;
    char *route_str = NULL;
    size_t body_len;
    size_t offset = 0;

    uint8_t flag; 
    uint8_t type;
    uint8_t compressRoute;

    // invalid req id for error msg
    // notify req id for push message
    uint32_t id = PC_INVALID_REQ_ID;

    if (len < PC_MSG_FLAG_BYTES) {
        return NULL;
    }

    flag = data[offset++];
    type = flag >> 1;
    compressRoute = flag & 0x01;

    if (!PC_MSG_VALIDATE(type)) {
        pc_lib_log(PC_LOG_ERROR, "pc_msg_decode_to_raw - unknow message type");
        return NULL; 
    }

    msg = (pc__msg_raw_t *)pc_lib_malloc(sizeof(pc__msg_raw_t));
    memset(msg, 0, sizeof(pc__msg_raw_t));

    msg->type = (pc_msg_type)type;
    msg->compressRoute = compressRoute;

    if(PC_MSG_HAS_ID(type)) {
        int i = 0;
        uint8_t m;
        id = 0;
     
        do{
            PC__MSG_CHECK_LEN(offset + 1, len);
            m = data[offset++];
            id = id + ((m & 0x7f) << (7 * i));
            i++;
        }while(m & 0x80);
    } else {
        id = PC_NOTIFY_PUSH_REQ_ID;
    }
    assert(id != PC_INVALID_REQ_ID);
    msg->id = id;

    // route
    if (PC_MSG_HAS_ROUTE(type)) {
        if(compressRoute) {
            PC__MSG_CHECK_LEN(offset + PC_MSG_ROUTE_CODE_BYTES, len);
            msg->route.route_code |= data[offset++] << 8;
            msg->route.route_code |= data[offset++];
        } else {
            size_t route_len;
            PC__MSG_CHECK_LEN(offset + PC_MSG_ROUTE_LEN_BYTES, len);
            route_len = data[offset++];
            PC__MSG_CHECK_LEN(offset + route_len, len);<commit_msg>pr_msg: fix decode bug for route code  when exceeding 128<commit_after>/**
 * Copyright (c) 2014 NetEase, Inc. and other Pomelo contributors
 * MIT Licensed.
 */

#include <assert.h>
#include <string.h>
#include <stdint.h>
#include <jansson.h>

#include <pc_lib.h>

#include "pr_msg.h"
#include "tr_uv_tcp_i.h"

#define PC_MSG_FLAG_BYTES 1
#define PC_MSG_ROUTE_LEN_BYTES 1
#define PC_MSG_ROUTE_CODE_BYTES 2

#define PC_MSG_HAS_ID(TYPE) ((TYPE) == PC_MSG_REQUEST ||                      \
        (TYPE) == PC_MSG_RESPONSE)

#define PC_MSG_HAS_ROUTE(TYPE) ((TYPE) != PC_MSG_RESPONSE)

#define PC_MSG_VALIDATE(TYPE) ((TYPE) == PC_MSG_REQUEST ||                    \
        (TYPE) == PC_MSG_NOTIFY ||                                            \
        (TYPE) == PC_MSG_RESPONSE ||                                          \
        (TYPE) == PC_MSG_PUSH)

/**
 * message type.
 */
typedef enum {
    PC_MSG_REQUEST = 0,
    PC_MSG_NOTIFY,
    PC_MSG_RESPONSE,
    PC_MSG_PUSH
} pc_msg_type;

typedef struct {
    uint32_t id;
    pc_msg_type type;
    uint8_t compressRoute;
    union {
        uint16_t route_code;
        const char *route_str;
    } route;
    pc_buf_t body;
} pc__msg_raw_t;

static PC_INLINE const char *pc__resolve_dictionary(const json_t* code2route, uint16_t code)
{
    char code_str[16];
    memset(code_str, 0, 16);
    sprintf(code_str, "%u", code);
    return json_string_value(json_object_get(code2route, code_str));
}

#define PC__MSG_CHECK_LEN(INDEX, LENGTH)                                      \
do {                                                                          \
    if((INDEX) > (LENGTH)) {                                                  \
        pc_lib_log(PC_LOG_ERROR, "pc_msg_decode_to_raw - invalid length");    \
        goto error;                                                           \
    }                                                                         \
} while(0)


static pc__msg_raw_t *pc_msg_decode_to_raw(const pc_buf_t* buf) 
{
    const char* data = buf->base;
    size_t len = buf->len;
    pc__msg_raw_t *msg = NULL;
    char *route_str = NULL;
    size_t body_len;
    size_t offset = 0;

    uint8_t flag; 
    uint8_t type;
    uint8_t compressRoute;

    // invalid req id for error msg
    // notify req id for push message
    uint32_t id = PC_INVALID_REQ_ID;

    if (len < PC_MSG_FLAG_BYTES) {
        return NULL;
    }

    flag = data[offset++];
    type = flag >> 1;
    compressRoute = flag & 0x01;

    if (!PC_MSG_VALIDATE(type)) {
        pc_lib_log(PC_LOG_ERROR, "pc_msg_decode_to_raw - unknow message type");
        return NULL; 
    }

    msg = (pc__msg_raw_t *)pc_lib_malloc(sizeof(pc__msg_raw_t));
    memset(msg, 0, sizeof(pc__msg_raw_t));

    msg->type = (pc_msg_type)type;
    msg->compressRoute = compressRoute;

    if(PC_MSG_HAS_ID(type)) {
        int i = 0;
        uint8_t m;
        id = 0;
     
        do{
            PC__MSG_CHECK_LEN(offset + 1, len);
            m = data[offset++];
            id = id + ((m & 0x7f) << (7 * i));
            i++;
        }while(m & 0x80);
    } else {
        id = PC_NOTIFY_PUSH_REQ_ID;
    }
    assert(id != PC_INVALID_REQ_ID);
    msg->id = id;

    // route
    if (PC_MSG_HAS_ROUTE(type)) {
        if(compressRoute) {
            PC__MSG_CHECK_LEN(offset + PC_MSG_ROUTE_CODE_BYTES, len);
            msg->route.route_code |= (uint8_t)data[offset++] << 8;
            msg->route.route_code |= (uint8_t)data[offset++];
        } else {
            size_t route_len;
            PC__MSG_CHECK_LEN(offset + PC_MSG_ROUTE_LEN_BYTES, len);
            route_len = data[offset++];
            PC__MSG_CHECK_LEN(offset + route_len, len);
{'fraction_non_alphanumeric': 0.10794213973799127, 'fraction_numerical': 0.012963973799126638, 'mean_word_length': 1.8091222690686086, 'pattern_counts': {'":': 0, '<': 23, '<?xml version=': 0, '>': 33, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 30, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1025263', 'n_tokens_mistral': 2598, 'n_tokens_neox': 2509, 'n_words': 498}