Пример #1
0
/*
 * It parse a JSON string and convert it to MessagePack format, this packer is
 * useful when a complete JSON message exists, otherwise it will fail until
 * the message is complete.
 *
 * This routine do not keep a state in the parser, do not use it for big
 * JSON messages.
 */
int flb_pack_json(char *js, size_t len, char **buffer, int *size)
{
    int ret;
    int out;
    char *buf;
    struct flb_pack_state state;

    ret = flb_pack_state_init(&state);
    if (ret != 0) {
        return -1;
    }
    ret = json_tokenise(js, len, &state);
    if (ret != 0) {
        return ret;
    }

    buf = tokens_to_msgpack(js, state.tokens, state.tokens_count, &out);
    if (!buf) {
        return -1;
    }

    *size = out;
    *buffer = buf;

    return 0;
}
Пример #2
0
/* Create a new mqtt request instance */
struct tcp_conn *tcp_conn_add(int fd, struct flb_in_tcp_config *ctx)
{
    int ret;
    struct tcp_conn *conn;
    struct mk_event *event;

    conn = flb_malloc(sizeof(struct tcp_conn));
    if (!conn) {
        return NULL;
    }

    /* Set data for the event-loop */
    event = &conn->event;
    MK_EVENT_NEW(event);
    event->fd           = fd;
    event->type         = FLB_ENGINE_EV_CUSTOM;
    event->handler      = tcp_conn_event;

    /* Connection info */
    conn->fd      = fd;
    conn->ctx     = ctx;
    conn->buf_len = 0;
    conn->rest    = 0;
    conn->status  = TCP_NEW;

    conn->buf_data = flb_malloc(ctx->chunk_size);
    if (!conn->buf_data) {
        perror("malloc");
        close(fd);
        flb_error("[in_tcp] could not allocate new connection");
        flb_free(conn);
        return NULL;
    }
    conn->buf_size = ctx->chunk_size;
    conn->in       = ctx->in;

    /* Initialize JSON parser */
    flb_pack_state_init(&conn->pack_state);

    /* Register instance into the event loop */
    ret = mk_event_add(ctx->evl, fd, FLB_ENGINE_EV_CUSTOM, MK_EVENT_READ, conn);
    if (ret == -1) {
        flb_error("[in_tcp] could not register new connection");
        close(fd);
        flb_free(conn->buf_data);
        flb_free(conn);
        return NULL;
    }

    mk_list_add(&conn->_head, &ctx->connections);

    return conn;
}
Пример #3
0
/* Initialize plugin */
int in_lib_init(struct flb_input_instance *in,
                struct flb_config *config, void *data)
{
    int ret;
    struct flb_in_lib_config *ctx;
    (void) data;

    /* Allocate space for the configuration */
    ctx = flb_malloc(sizeof(struct flb_in_lib_config));
    if (!ctx) {
        return -1;
    }

    ctx->buf_size = LIB_BUF_CHUNK;
    ctx->buf_data = flb_calloc(1, LIB_BUF_CHUNK);
    ctx->buf_len = 0;

    if (!ctx->buf_data) {
        flb_utils_error_c("Could not allocate initial buf memory buffer");
    }

    ctx->msgp_size = LIB_BUF_CHUNK;
    ctx->msgp_data = flb_malloc(LIB_BUF_CHUNK);
    ctx->msgp_len = 0;

    /* Init communication channel */
    flb_input_channel_init(in);
    ctx->fd = in->channel[0];

    if (!ctx->msgp_data) {
        flb_utils_error_c("Could not allocate initial msgp memory buffer");
    }

    /* Set the context */
    flb_input_set_context(in, ctx);

    /* Collect upon data available on the standard input */
    ret = flb_input_set_collector_event(in,
                                        in_lib_collect,
                                        ctx->fd,
                                        config);
    if (ret == -1) {
        flb_utils_error_c("Could not set collector for LIB input plugin");
    }

    flb_pack_state_init(&ctx->state);
    return 0;
}
Пример #4
0
int in_lib_collect(struct flb_config *config, void *in_context)
{
    int n;
    int ret;
    int bytes;
    int out_size;
    int capacity;
    int size;
    char *ptr;
    char *pack;
    struct flb_in_lib_config *ctx = in_context;

    capacity = (ctx->buf_size - ctx->buf_len);

    /* Allocate memory as required (FIXME: this will be limited in later) */
    if (capacity == 0) {
        size = ctx->buf_size + LIB_BUF_CHUNK;
        ptr = flb_realloc(ctx->buf_data, size);
        if (!ptr) {
            perror("realloc");
            return -1;
        }
        ctx->buf_data = ptr;
        ctx->buf_size = size;
        capacity = LIB_BUF_CHUNK;
    }

    bytes = read(ctx->fd,
                 ctx->buf_data + ctx->buf_len,
                 capacity);
    flb_trace("in_lib read() = %i", bytes);
    if (bytes == -1) {
        perror("read");
        if (errno == -EPIPE) {
            return -1;
        }
        return 0;
    }
    ctx->buf_len += bytes;

    /* initially we should support json input */
    ret = flb_pack_json_state(ctx->buf_data, ctx->buf_len,
                              &pack, &out_size, &ctx->state);
    if (ret == FLB_ERR_JSON_PART) {
        flb_warn("lib data incomplete, waiting for more data...");
        return 0;
    }
    else if (ret == FLB_ERR_JSON_INVAL) {
        flb_warn("lib data invalid");
        flb_pack_state_reset(&ctx->state);
        flb_pack_state_init(&ctx->state);
        return -1;
    }
    ctx->buf_len = 0;

    capacity = (ctx->msgp_size - ctx->msgp_len);
    if (capacity < out_size) {
        n = ((out_size - capacity) / LIB_BUF_CHUNK) + 1;
        size = ctx->msgp_size + (LIB_BUF_CHUNK * n);
        ptr = flb_realloc(ctx->msgp_data, size);
        if (!ptr) {
            perror("realloc");
            flb_free(pack);
            flb_pack_state_reset(&ctx->state);
            flb_pack_state_init(&ctx->state);
            return -1;
        }
        ctx->msgp_data = ptr;
        ctx->msgp_size = size;
    }

    memcpy(ctx->msgp_data + ctx->msgp_len, pack, out_size);
    ctx->msgp_len += out_size;
    flb_free(pack);

    flb_pack_state_reset(&ctx->state);
    flb_pack_state_init(&ctx->state);

    return 0;
}
Пример #5
0
/* Callback invoked every time an event is triggered for a connection */
int tcp_conn_event(void *data)
{
    int ret;
    int bytes;
    int available;
    int size;
    char *tmp;
    struct mk_event *event;
    struct tcp_conn *conn = data;
    struct flb_in_tcp_config *ctx = conn->ctx;
    jsmntok_t *t;

    event = &conn->event;
    if (event->mask & MK_EVENT_READ) {
        available = (conn->buf_size - conn->buf_len);
        if (available < 1) {
            if (conn->buf_size + ctx->chunk_size > ctx->buffer_size) {
                flb_trace("[in_tcp] fd=%i incoming data exceed limit (%i KB)",
                          event->fd, (ctx->buffer_size / 1024));
                tcp_conn_del(conn);
                return -1;
            }

            size = conn->buf_size + ctx->chunk_size;
            tmp = flb_realloc(conn->buf_data, size);
            if (!tmp) {
                perror("realloc");
                return -1;
            }
            flb_trace("[in_tcp] fd=%i buffer realloc %i -> %i",
                      event->fd, conn->buf_size, size);

            conn->buf_data = tmp;
            conn->buf_size = size;
            available = (conn->buf_size - conn->buf_len);
        }

        /* Read data */
        bytes = read(conn->fd,
                     conn->buf_data + conn->buf_len, available);
        if (bytes <= 0) {
            flb_trace("[in_tcp] fd=%i closed connection", event->fd);
            tcp_conn_del(conn);
            return -1;
        }

        flb_trace("[in_tcp] read()=%i pre_len=%i now_len=%i",
                  bytes, conn->buf_len, conn->buf_len + bytes);
        conn->buf_len += bytes;
        conn->buf_data[conn->buf_len] = '\0';

        /* Strip CR or LF if found at first byte */
        if (conn->buf_data[0] == '\r' || conn->buf_data[0] == '\n') {
            /* Skip message with one byte with CR or LF */
            flb_trace("[in_tcp] skip one byte message with ASCII code=%i",
                      conn->buf_data[0]);
            consume_bytes(conn->buf_data, 1, conn->buf_len);
            conn->buf_len--;
        }


        /* JSON Format handler */
        char *pack;
        int out_size;

        ret = flb_pack_json_state(conn->buf_data, conn->buf_len,
                                  &pack, &out_size, &conn->pack_state);
        if (ret == FLB_ERR_JSON_PART) {
            flb_debug("[in_serial] JSON incomplete, waiting for more data...");
            return 0;
        }
        else if (ret == FLB_ERR_JSON_INVAL) {
            flb_debug("[in_serial] invalid JSON message, skipping");
            flb_pack_state_reset(&conn->pack_state);
            flb_pack_state_init(&conn->pack_state);
            conn->pack_state.multiple = FLB_TRUE;

            return -1;
        }

        /*
         * Given the Tokens used for the packaged message, append
         * the records and then adjust buffer.
         */
        process_pack(conn, pack, out_size);

        t = &conn->pack_state.tokens[0];
        consume_bytes(conn->buf_data, t->end, conn->buf_len);
        conn->buf_len -= t->end;
        conn->buf_data[conn->buf_len] = '\0';

        flb_pack_state_reset(&conn->pack_state);
        flb_pack_state_init(&conn->pack_state);
        conn->pack_state.multiple = FLB_TRUE;

        flb_free(pack);
        return bytes;
    }

    if (event->mask & MK_EVENT_CLOSE) {
        flb_trace("[in_tcp] fd=%i hangup", event->fd);
        tcp_conn_del(conn);
        return -1;
    }
    return 0;
}
Пример #6
0
/* Init serial input */
int in_serial_init(struct flb_input_instance *in,
                   struct flb_config *config, void *data)
{
    int fd;
    int ret;
    int br;
    struct flb_in_serial_config *ctx;
    (void) data;

    ctx = flb_calloc(1, sizeof(struct flb_in_serial_config));
    if (!ctx) {
        perror("calloc");
        return -1;
    }
    ctx->format = FLB_SERIAL_FORMAT_NONE;

    if (!serial_config_read(ctx, in)) {
        return -1;
    }

    /* Initialize JSON pack state */
    if (ctx->format == FLB_SERIAL_FORMAT_JSON) {
        flb_pack_state_init(&ctx->pack_state);
    }

    /* set context */
    flb_input_set_context(in, ctx);

    /* initialize MessagePack buffers */
    msgpack_sbuffer_init(&ctx->mp_sbuf);
    msgpack_packer_init(&ctx->mp_pck, &ctx->mp_sbuf, msgpack_sbuffer_write);

    /* open device */
    fd = open(ctx->file, O_RDWR | O_NOCTTY | O_NONBLOCK);
    if (fd == -1) {
        perror("open");
        flb_error("[in_serial] Could not open serial port device");
        flb_free(ctx);
        return -1;
    }
    ctx->fd = fd;

    /* Store original settings */
    tcgetattr(fd, &ctx->tio_orig);

    /* Reset for new... */
    memset(&ctx->tio, 0, sizeof(ctx->tio));
    tcgetattr(fd, &ctx->tio);

    br = atoi(ctx->bitrate);
    cfsetospeed(&ctx->tio, (speed_t) flb_serial_speed(br));
    cfsetispeed(&ctx->tio, (speed_t) flb_serial_speed(br));

    /* Settings */
    ctx->tio.c_cflag     &=  ~PARENB;        /* 8N1 */
    ctx->tio.c_cflag     &=  ~CSTOPB;
    ctx->tio.c_cflag     &=  ~CSIZE;
    ctx->tio.c_cflag     |=  CS8;
    ctx->tio.c_cflag     &=  ~CRTSCTS;       /* No flow control */
    ctx->tio.c_cc[VMIN]   =  ctx->min_bytes; /* Min number of bytes to read  */
    ctx->tio.c_cflag     |=  CREAD | CLOCAL; /* Enable READ & ign ctrl lines */

    tcflush(fd, TCIFLUSH);
    tcsetattr(fd, TCSANOW, &ctx->tio);

#if __linux__
    /* Set our collector based on a file descriptor event */
    ret = flb_input_set_collector_event(in,
                                        in_serial_collect,
                                        ctx->fd,
                                        config);
#else
    /* Set our collector based on a timer event */
    ret = flb_input_set_collector_time(in,
                                       in_serial_collect,
                                       IN_SERIAL_COLLECT_SEC,
                                       IN_SERIAL_COLLECT_NSEC,
                                       config);
#endif
    return ret;
}
Пример #7
0
/* Callback triggered when some serial msgs are available */
int in_serial_collect(struct flb_config *config, void *in_context)
{
    int ret;
    int bytes = 0;
    int available;
    int len;
    int hits;
    char *sep;
    char *buf;
    jsmntok_t *t;

    struct flb_in_serial_config *ctx = in_context;

    while (1) {
        available = (sizeof(ctx->buf_data) -1) - ctx->buf_len;
        if (available > 1) {
            bytes = read(ctx->fd, ctx->buf_data + ctx->buf_len, available);
            if (bytes == -1) {
                if (errno == EPIPE || errno == EINTR) {
                    return -1;
                }
                return 0;
            }
            else if (bytes == 0) {
                return 0;
            }
        }
        ctx->buf_len += bytes;

        /* Always set a delimiter to avoid buffer trash */
        ctx->buf_data[ctx->buf_len] = '\0';

        /* Check if our buffer is full */
        if (ctx->buffer_id + 1 == SERIAL_BUFFER_SIZE) {
            ret = flb_engine_flush(config, &in_serial_plugin);
            if (ret == -1) {
                ctx->buffer_id = 0;
            }
        }

        sep = NULL;
        buf = ctx->buf_data;
        len = ctx->buf_len;
        hits = 0;

        /* Handle FTDI handshake */
        if (ctx->buf_data[0] == '\0') {
            consume_bytes(ctx->buf_data, 1, ctx->buf_len);
            ctx->buf_len--;
        }

        /* Strip CR or LF if found at first byte */
        if (ctx->buf_data[0] == '\r' || ctx->buf_data[0] == '\n') {
            /* Skip message with one byte with CR or LF */
            flb_trace("[in_serial] skip one byte message with ASCII code=%i",
                      ctx->buf_data[0]);
            consume_bytes(ctx->buf_data, 1, ctx->buf_len);
            ctx->buf_len--;
        }

        /* Handle the case when a Separator is set */
        if (ctx->separator) {
            while ((sep = strstr(ctx->buf_data, ctx->separator))) {
                len = (sep - ctx->buf_data);
                if (len > 0) {
                    /* process the line based in the separator position */
                    process_line(buf, len, ctx);
                    consume_bytes(ctx->buf_data, len + ctx->sep_len, ctx->buf_len);
                    ctx->buf_len -= (len + ctx->sep_len);
                    hits++;
                }
                else {
                    consume_bytes(ctx->buf_data, ctx->sep_len, ctx->buf_len);
                    ctx->buf_len -= ctx->sep_len;
                }
                ctx->buf_data[ctx->buf_len] = '\0';
            }

            if (hits == 0 && available <= 1) {
                flb_debug("[in_serial] no separator found, no more space");
                ctx->buf_len = 0;
                return 0;
            }
        }
        else if (ctx->format == FLB_SERIAL_FORMAT_JSON) {
            /* JSON Format handler */
            char *pack;
            int out_size;

            ret = flb_pack_json_state(ctx->buf_data, ctx->buf_len,
                                      &pack, &out_size, &ctx->pack_state);
            if (ret == FLB_ERR_JSON_PART) {
                flb_debug("[in_serial] JSON incomplete, waiting for more data...");
                return 0;
            }
            else if (ret == FLB_ERR_JSON_INVAL) {
                flb_debug("[in_serial] invalid JSON message, skipping");
                flb_pack_state_reset(&ctx->pack_state);
                flb_pack_state_init(&ctx->pack_state);
                ctx->pack_state.multiple = FLB_TRUE;

                return -1;
            }

            /*
             * Given the Tokens used for the packaged message, append
             * the records and then adjust buffer.
             */
            process_pack(ctx, pack, out_size);
            flb_free(pack);

            t = &ctx->pack_state.tokens[0];
            consume_bytes(ctx->buf_data, t->end, ctx->buf_len);
            ctx->buf_len -= t->end;
            ctx->buf_data[ctx->buf_len] = '\0';

            flb_pack_state_reset(&ctx->pack_state);
            flb_pack_state_init(&ctx->pack_state);
            ctx->pack_state.multiple = FLB_TRUE;
        }
        else {
            /* Process and enqueue the received line */
            process_line(ctx->buf_data, ctx->buf_len, ctx);
            ctx->buf_len = 0;
        }
    }

    return 0;
}