Exemplo n.º 1
0
/* Creates a new upstream context */
struct flb_io_upstream *flb_io_upstream_new(char *host, int port, int flags)
{
    int fd;
    struct flb_io_upstream *u;

    u = malloc(sizeof(struct flb_io_upstream));
    if (!u) {
        perror("malloc");
        return NULL;
    }


    /* Upon upstream creation, we always try to perform a connection */
    flb_debug("[upstream] connecting to %s:%i", host, port);
    fd = flb_net_tcp_connect(host, port);
    if (fd == -1) {
        flb_warn("[upstream] could not connect to %s:%i", host, port);
    }
    else {
        flb_debug("[upstream] connected!");
    }

    u->fd   = fd;
    u->tcp_host = strdup(host);
    u->tcp_port = port;
    u->flags    = flags;

    return u;
}
Exemplo n.º 2
0
/* Write data to an upstream connection/server */
int flb_io_net_write(struct flb_io_upstream *u, void *data,
                     size_t len, size_t *out_len)
{
    int ret = -1;
    struct flb_thread *th;

    flb_debug("[io] trying to write %zd bytes", len);

    th = pthread_getspecific(flb_thread_key);
    if (u->flags & FLB_IO_TCP) {
        ret = net_io_write(th, u, data, len, out_len);
    }
#ifdef HAVE_TLS
    else if (u->flags & FLB_IO_TLS) {
        ret = net_io_tls_write(th, u, data, len, out_len);
    }
#endif

    if (ret == -1 && u->fd > 0) {
        close(u->fd);
        u->fd = -1;
    }

    flb_debug("[io] thread has finished");
    return ret;
}
Exemplo n.º 3
0
int cb_td_flush(void *data, size_t bytes, void *out_context,
                struct flb_config *config)
{
    int n;
    int ret;
    int bytes_out;
    char *pack;
    size_t bytes_sent;
    char buf[1024];
    size_t len;
    char *request;
    struct flb_out_td_config *ctx = out_context;

    /* Convert format */
    pack = td_format(data, bytes, &bytes_out);
    if (!pack) {
        return -1;
    }

    request = td_http_request(pack, bytes_out, &len, ctx, config);
    ret = flb_io_net_write(ctx->u, request, len, &bytes_sent);
    if (ret == -1) {
        perror("write");
    }
    free(request);
    free(pack);

    n = flb_io_net_read(ctx->u, buf, sizeof(buf) - 1);
    if (n > 0) {
        buf[n] = '\0';
        flb_debug("[TD] API server response:\n%s", buf);
    }

    return bytes_sent;
}
Exemplo n.º 4
0
struct flb_in_serial_config *serial_config_read(struct flb_in_serial_config *config,
                                                struct mk_rconf *conf)
{
    char *file;
    char *bitrate;
    struct mk_rconf_section *section;

    section = mk_rconf_section_get(conf, "serial");
    if (!section) {
        return NULL;
    }

    /* Validate serial section keys */
    file = mk_rconf_section_get_key(section, "file", MK_RCONF_STR);
    bitrate = mk_rconf_section_get_key(section, "bitrate", MK_RCONF_STR);

    if (!file) {
        flb_utils_error_c("[serial] error reading filename from "
                "configuration");
    }

    if (!bitrate) {
        flb_utils_error_c("[serial] error reading bitrate from "
                "configuration");
    }

    config->fd       = -1;
    config->file     = file;
    config->bitrate  = bitrate;

    flb_debug("Serial / file='%s' bitrate='%s'",
              config->file, config->bitrate);

    return config;
}
Exemplo n.º 5
0
int cb_td_flush(void *data, size_t bytes, void *out_context,
                struct flb_config *config)
{
    int n;
    char buf[1024];
    ssize_t w_bytes;
    size_t out_len;
    char *request;
    struct flb_out_td_config *ctx = out_context;

    request = td_http_request(data, bytes, &out_len, ctx, config);
    w_bytes = write(ctx->fd, request, out_len);
    if (w_bytes < 0) {
        perror("write");
        /* FIXME: handle connection timeout */
        if (errno == EBADF) {
            close(ctx->fd);
            ctx->fd = flb_net_tcp_connect(out_td_plugin.host,
                                          out_td_plugin.port);
        }
    }
    free(request);

    n = read(ctx->fd, buf, 4096);
    buf[n] = '\0';

    flb_debug("[TD] API server response:\n%s", buf);
    return w_bytes;
}
Exemplo n.º 6
0
/* Cleanup serial input */
int in_serial_exit(void *in_context, struct flb_config *config)
{
    struct flb_in_serial_config *ctx = in_context;

    flb_debug("[in_serial] Restoring original termios...");
    tcsetattr(ctx->fd, TCSANOW, &ctx->tio_orig);
}
Exemplo n.º 7
0
FLB_INLINE int net_io_tls_write(struct flb_thread *th, struct flb_io_upstream *u,
                     void *data, size_t len, size_t *out_len)
{
    int ret;
    size_t total = 0;

    if (!u->tls_session) {
        u->tls_session = flb_tls_session_new(u->tls->context);
        if (!u->tls_session) {
            flb_error("[io_tls] could not create tls session");
            return -1;
        }

        ret = flb_io_net_tls_connect(u, th);
        if (ret == -1) {
            flb_error("[io_tls] could not connect/initiate TLS session");
            return -1;
        }
    }

 retry_write:
    ret = mbedtls_ssl_write(&u->tls_session->ssl,
                            data + total,
                            len - total);
    if (ret == MBEDTLS_ERR_SSL_WANT_WRITE) {
        io_tls_event_switch(u, MK_EVENT_WRITE);
        flb_thread_yield(th, FLB_FALSE);
        goto retry_write;
    }
    else if (ret == MBEDTLS_ERR_SSL_WANT_READ) {
        io_tls_event_switch(u, MK_EVENT_READ);
        flb_thread_yield(th, FLB_FALSE);
        goto retry_write;
    }
    else if (ret < 0) {
        char err_buf[72];
        mbedtls_strerror(ret, err_buf, sizeof(err_buf));
        flb_debug("[tls] SSL error: %s", err_buf);

        /* There was an error transmitting data */
        mk_event_del(u->evl, &u->event);
        tls_session_destroy(u->tls_session);
        u->tls_session = NULL;
        return -1;
    }

    /* Update statistics */
    //flb_stats_update(out->stats_fd, ret, 0);

    /* Update counter and check if we need to continue writing */
    total += ret;
    if (total < len) {
        io_tls_event_switch(u, MK_EVENT_WRITE);
        flb_thread_yield(th, FLB_FALSE);
        goto retry_write;
    }

    mk_event_del(u->evl, &u->event);
    return 0;
}
Exemplo n.º 8
0
void in_xbee_cb(struct xbee *xbee, struct xbee_con *con,
                struct xbee_pkt **pkt, void **data)
{
    struct iovec *v;
    struct flb_in_xbee_config *ctx;

	if ((*pkt)->dataLen == 0) {
		flb_debug("xbee data length too short, skip");
		return;
	}

    ctx = *data;

    if (ctx->buffer_len + 1 >= FLB_XBEE_BUFFER_SIZE) {
        /* fixme: use flb_engine_flush() */
        return;
    }

    /* Insert entry into the iovec */
    v = &ctx->buffer[ctx->buffer_len];
    v->iov_base = malloc((*pkt)->dataLen);
    memcpy(v->iov_base, (*pkt)->data, (*pkt)->dataLen);
    v->iov_len = (*pkt)->dataLen;
    ctx->buffer_len++;
}
Exemplo n.º 9
0
int in_mem_collect(struct flb_config *config, void *in_context)
{
    struct sysinfo info;
    (void) config;
    struct flb_in_mem_config *ctx = in_context;
    uint32_t totalram, freeram;

    sysinfo(&info);
    totalram = info.totalram / 1024;
    freeram  = info.freeram  / 1024;
    msgpack_pack_map(&ctx->pckr, 3);
    msgpack_pack_raw(&ctx->pckr, 4);
    msgpack_pack_raw_body(&ctx->pckr, "time", 4);
    msgpack_pack_uint64(&ctx->pckr, time(NULL));
    msgpack_pack_raw(&ctx->pckr, 5);
    msgpack_pack_raw_body(&ctx->pckr, "total", 5);
    msgpack_pack_uint32(&ctx->pckr, totalram);
    msgpack_pack_raw(&ctx->pckr, 4);
    msgpack_pack_raw_body(&ctx->pckr, "free", 4);
    msgpack_pack_uint32(&ctx->pckr, freeram);
    flb_debug("[in_mem] memory total %d kb, free %d kb (buffer=%i)",
              info.totalram,
              info.freeram,
              ctx->idx);
    ++ctx->idx;
    return 0;
}
Exemplo n.º 10
0
static int json_tokenise(char *js, size_t len,
                         struct flb_pack_state *state)
{
    int ret;
    int n;
    void *tmp;

    ret = jsmn_parse(&state->parser, js, len,
                     state->tokens, state->tokens_size);
    while (ret == JSMN_ERROR_NOMEM) {
        n = state->tokens_size += 256;
        tmp = realloc(state->tokens, sizeof(jsmntok_t) * n);
        if (!tmp) {
            perror("realloc");
            return -1;
        }
        state->tokens = tmp;
        state->tokens_size = n;
        ret = jsmn_parse(&state->parser, js, len,
                         state->tokens, state->tokens_size);
    }

    if (ret == JSMN_ERROR_INVAL) {
        return FLB_ERR_JSON_INVAL;
    }

    if (ret == JSMN_ERROR_PART) {
        /* This is a partial JSON message, just stop */
        flb_debug("[json tokenise] incomplete");
        return FLB_ERR_JSON_PART;
    }

    state->tokens_count += ret;
    return 0;
}
Exemplo n.º 11
0
static inline int process_line(char *line, struct flb_in_serial_config *ctx)
{
    int line_len;
    char *p = line;
    char *end = NULL;
    char msg[1024];

    /* Increase buffer position */
    ctx->buffer_id++;

    line_len = strlen(p);
    strncpy(msg, p, line_len);
    msg[line_len] = '\0';

    /*
     * Store the new data into the MessagePack buffer,
     * we handle this as a list of maps.
     */
    msgpack_pack_array(&ctx->mp_pck, 2);
    msgpack_pack_uint64(&ctx->mp_pck, time(NULL));

    msgpack_pack_map(&ctx->mp_pck, 1);
    msgpack_pack_bin(&ctx->mp_pck, 3);
    msgpack_pack_bin_body(&ctx->mp_pck, "msg", 3);
    msgpack_pack_bin(&ctx->mp_pck, line_len);
    msgpack_pack_bin_body(&ctx->mp_pck, p, line_len);

    flb_debug("[in_serial] '%s'",
              (const char *) msg);

    return 0;
}
Exemplo n.º 12
0
ssize_t flb_io_net_read(struct flb_io_upstream *u, void *buf, size_t len)
{
    int ret = -1;
    struct flb_thread *th;

    flb_debug("[io] trying to read up to %zd bytes", len);

    th = pthread_getspecific(flb_thread_key);
    if (u->flags & FLB_IO_TCP) {
        ret = net_io_read(th, u, buf, len);
    }
#ifdef HAVE_TLS
    else if (u->flags & FLB_IO_TLS) {
        ret = net_io_tls_read(th, u, buf, len);
    }
#endif

    flb_debug("[io] thread has finished");
    return ret;
}
Exemplo n.º 13
0
/* Callback to gather CPU usage between now and previous snapshot */
int in_cpu_collect(struct flb_config *config, void *in_context)
{
    int i;
    int maps;
    int len;
    double usage;
    double total;
    (void) config;
    struct flb_in_cpu_config *ctx = in_context;
    struct cpu_stats *cstats = &ctx->cstats;
    struct cpu_snapshot *s;

    /* Get the current CPU usage */
    total = proc_cpu_load(ctx->n_processors, cstats);
    cstats->load_now = total;

    /* Calculate the difference between the two samples */
    usage = fabs(cstats->load_now - cstats->load_pre) / ctx->cpu_ticks;
    total = (usage * 100) / ctx->n_processors;

    /* Put current load back */
    cstats->load_pre = cstats->load_now;

    /*
     * Store the new data into the MessagePack buffer,
     */
    msgpack_pack_array(&ctx->mp_pck, 2);
    msgpack_pack_uint64(&ctx->mp_pck, time(NULL));

    msgpack_pack_map(&ctx->mp_pck, (ctx->n_processors * 7 ) + 1);
    msgpack_pack_bin(&ctx->mp_pck, 3);
    msgpack_pack_bin_body(&ctx->mp_pck, "cpu", 3);
    msgpack_pack_double(&ctx->mp_pck, total);

    for (i = 1; i < ctx->n_processors + 1; i++) {
        s = &cstats->info[i];

        CPU_PACK_SNAP(s, user);
        CPU_PACK_SNAP(s, nice);
        CPU_PACK_SNAP(s, system);
        CPU_PACK_SNAP(s, idle);
        CPU_PACK_SNAP(s, iowait);
        CPU_PACK_SNAP(s, irq);
        CPU_PACK_SNAP(s, softirq);
    }

    flb_debug("[in_cpu] CPU %0.2f%%", total);

    flb_stats_update(in_cpu_plugin.stats_fd, 0, 1);
    return 0;
}
Exemplo n.º 14
0
/* Callback triggered by timer */
int in_xbee_collect(struct flb_config *config, void *in_context)
{
    int ret;
    void *p = NULL;
    (void) config;
    struct flb_in_xbee_config *ctx = in_context;

    if ((ret = xbee_conCallbackGet(ctx->con,
                                   (xbee_t_conCallback*) &p)) != XBEE_ENONE) {
        flb_debug("xbee_conCallbackGet() returned: %d", ret);
        return ret;
    }

    return 0;
}
Exemplo n.º 15
0
static inline int process_line(char *line, struct flb_in_serial_config *ctx)
{
    int line_len;
    uint64_t val;
    char *p = line;
    char *end = NULL;
    char msg[1024];

    /* Increase buffer position */
    ctx->buffer_id++;

    errno = 0;
    val = strtol(p, &end, 10);
    if ((errno == ERANGE && (val == INT_MAX || val == INT_MIN))
        || (errno != 0 && val == 0)) {
        goto fail;
    }

    /* Now process the human readable message */

    line_len = strlen(p);
    strncpy(msg, p, line_len);
    msg[line_len] = '\0';

    /*
     * Store the new data into the MessagePack buffer,
     * we handle this as a list of maps.
     */
    msgpack_pack_array(&ctx->mp_pck, 2);
    msgpack_pack_uint64(&ctx->mp_pck, time(NULL));

    msgpack_pack_map(&ctx->mp_pck, 1);
    msgpack_pack_bin(&ctx->mp_pck, 3);
    msgpack_pack_bin_body(&ctx->mp_pck, "msg", 3);
    msgpack_pack_bin(&ctx->mp_pck, line_len);
    msgpack_pack_bin_body(&ctx->mp_pck, p, line_len);

    flb_debug("[in_serial] '%s'",
              (const char *) msg);

    return 0;

 fail:
    ctx->buffer_id--;
    return -1;
}
Exemplo n.º 16
0
void cb_es_flush(void *data, size_t bytes,
                 char *tag, int tag_len,
                 struct flb_input_instance *i_ins, void *out_context,
                 struct flb_config *config)
{
    int ret;
    int bytes_out;
    char *pack;
    size_t b_sent;
    struct flb_out_es_config *ctx = out_context;
    struct flb_upstream_conn *u_conn;
    struct flb_http_client *c;
    (void) i_ins;
    (void) tag;
    (void) tag_len;

    /* Convert format */
    pack = es_format(data, bytes, &bytes_out, ctx);
    if (!pack) {
        FLB_OUTPUT_RETURN(FLB_ERROR);
    }

    /* Get upstream connection */
    u_conn = flb_upstream_conn_get(ctx->u);
    if (!u_conn) {
        flb_free(pack);
        FLB_OUTPUT_RETURN(FLB_RETRY);
    }

    /* Compose HTTP Client request */
    c = flb_http_client(u_conn, FLB_HTTP_POST, "/_bulk",
                        pack, bytes_out, NULL, 0, NULL);
    flb_http_add_header(c, "User-Agent", 10, "Fluent-Bit", 10);
    flb_http_add_header(c, "Content-Type", 12, "application/json", 16);

    ret = flb_http_do(c, &b_sent);
    flb_debug("[out_es] http_do=%i", ret);
    flb_http_client_destroy(c);

    flb_free(pack);

    /* Release the connection */
    flb_upstream_conn_release(u_conn);
    FLB_OUTPUT_RETURN(FLB_OK);
}
Exemplo n.º 17
0
/* Initialize plugin */
int in_mqtt_init(struct flb_input_instance *in,
                 struct flb_config *config, void *data)
{
    int ret;
    struct flb_in_mqtt_config *ctx;
    (void) data;

    /* Allocate space for the configuration */
    ctx = mqtt_config_init(in);
    if (!ctx) {
        return -1;
    }
    ctx->msgp_len = 0;

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

    /* Create TCP server */
    ctx->server_fd = flb_net_server(ctx->tcp_port, ctx->listen);
    if (ctx->server_fd > 0) {
        flb_debug("[in_mqtt] binding %s:%s", ctx->listen, ctx->tcp_port);
    }
    else {
        flb_error("[in_mqtt] could not bind address %s:%s",
                  ctx->listen, ctx->tcp_port);
        mqtt_config_free(ctx);
        return -1;
    }
    ctx->evl = config->evl;

    /* Collect upon data available on the standard input */
    ret = flb_input_set_collector_event(in,
                                        in_mqtt_collect,
                                        ctx->server_fd,
                                        config);
    if (ret == -1) {
        flb_error("[in_mqtt] Could not set collector for MQTT input plugin");
        mqtt_config_free(ctx);
        return -1;
    }

    return 0;
}
Exemplo n.º 18
0
struct flb_out_td_config *td_config_init(struct mk_rconf *conf)
{
    char *api;
    char *db_name;
    char *db_table;
    struct mk_rconf_section *section;
    struct flb_out_td_config *config;

    section = mk_rconf_section_get(conf, "TD");
    if (!section) {
        return NULL;
    }

    /* Validate TD section keys */
    api = mk_rconf_section_get_key(section, "API", MK_RCONF_STR);
    db_name = mk_rconf_section_get_key(section, "Database", MK_RCONF_STR);
    db_table = mk_rconf_section_get_key(section, "Table", MK_RCONF_STR);

    if (!api) {
        flb_utils_error_c("[TD] error reading API key value");
    }

    if (!db_name) {
        flb_utils_error_c("[TD] error reading Database name");
    }

    if (!db_table) {
        flb_utils_error_c("[TD] error reading Table name");
    }

    config = malloc(sizeof(struct flb_out_td_config));
    config->fd       = -1;
    config->api      = api;
    config->db_name  = db_name;
    config->db_table = db_table;

    flb_debug("TreasureData / database='%s' table='%s'",
              config->db_name, config->db_table);

    return config;
}
Exemplo n.º 19
0
static inline int process_line(char *line, int len,
                               struct flb_in_serial_config *ctx)
{
    /* Increase buffer position */
    ctx->buffer_id++;

    /*
     * Store the new data into the MessagePack buffer,
     * we handle this as a list of maps.
     */
    msgpack_pack_array(&ctx->mp_pck, 2);
    msgpack_pack_uint64(&ctx->mp_pck, time(NULL));

    msgpack_pack_map(&ctx->mp_pck, 1);
    msgpack_pack_bin(&ctx->mp_pck, 3);
    msgpack_pack_bin_body(&ctx->mp_pck, "msg", 3);
    msgpack_pack_bin(&ctx->mp_pck, len);
    msgpack_pack_bin_body(&ctx->mp_pck, line, len);

    flb_debug("[in_serial] message '%s'",
              (const char *) line);

    return 0;
}
Exemplo n.º 20
0
void in_xbee_cb(struct xbee *xbee, struct xbee_con *con,
                struct xbee_pkt **pkt, void **data)
{
    struct flb_in_xbee_config *ctx;

    if ((*pkt)->dataLen == 0) {
        flb_debug("xbee data length too short, skip");
        return;
    }

    ctx = *data;

#if 0
    int i;
    for (i = 0; i < (*pkt)->dataLen; i++) {
        printf("%2.2x ", *((unsigned char*) (*pkt)->data + i));
    }
    printf("\n");
#endif

    if (! in_xbee_rx_queue_msgpack(ctx, (const char*) (*pkt)->data, (*pkt)->dataLen)) {
        in_xbee_rx_queue_raw(ctx, (const char*) (*pkt)->data, (*pkt)->dataLen);
    }
}
Exemplo n.º 21
0
static inline int process_line(char *line, struct flb_in_kmsg_config *ctx)
{
    uint64_t val;
    char *p = line;
    char *end = NULL;
    struct kmsg_line *buf;

    /* Increase buffer position */
    ctx->buffer_id++;

    errno = 0;
    val = strtol(p, &end, 10);
    if ((errno == ERANGE && (val == INT_MAX || val == INT_MIN))
        || (errno != 0 && val == 0)) {
        goto fail;
    }

    /* Lookup */
    buf = &ctx->buffer[ctx->buffer_id];

    /* Priority */
    buf->priority = FLB_LOG_PRI(val);

    /* Sequence */
    p = strchr(p, ',');
    p++;

    val = strtol(p, &end, 10);
    if ((errno == ERANGE && (val == INT_MAX || val == INT_MIN))
        || (errno != 0 && val == 0)) {
        goto fail;
    }

    buf->sequence = val;
    p = ++end;

    /* Timestamp */
    val = strtol(p, &end, 10);
    if ((errno == ERANGE && (val == INT_MAX || val == INT_MIN))
        || (errno != 0 && val == 0)) {
        goto fail;
    }
    buf->tv.tv_sec = val;

    if (*end == '.') {
        p = ++end;
        val = strtol(p, &end, 10);
        if ((errno == ERANGE && (val == INT_MAX || val == INT_MIN))
            || (errno != 0 && val == 0)) {
            goto fail;
        }
        buf->tv.tv_usec = val;
    }
    else {
        buf->tv.tv_usec = 0;
    }

    /* Now process the human readable message */
    p = strchr(p, ';');
    if (!p) {
        goto fail;
    }
    p++;

    buf->line_len = strlen(p);
    strncpy(buf->line, p, buf->line_len);
    buf->line[buf->line_len] = '\0';

    flb_debug("[in_kmsg] pri=%i seq=%" PRIu64 " sec=%ld usec=%ld '%s'",
              buf->priority,
              buf->sequence,
              (long int) buf->tv.tv_sec,
              (long int) buf->tv.tv_usec,
              (const char *) buf->line);

    return 0;


 fail:
    ctx->buffer_id--;
    return -1;
}
Exemplo n.º 22
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;
}
Exemplo n.º 23
0
/* It parse a JSON string and convert it to MessagePack format */
char *flb_pack_json(char *js, size_t len, int *size)
{
    int i;
    int flen;
    int arr_size;
    char *p;
    char *buf;
    jsmntok_t *t;
    jsmntok_t *tokens;
    msgpack_packer pck;
    msgpack_sbuffer sbuf;

    if (!js) {
        return NULL;
    }

    tokens = json_tokenise(js, len, &arr_size);
    if (!tokens) {
        return NULL;
    }

    flb_debug("JSON to pack: '%s'", js);

    /* initialize buffers */
    msgpack_sbuffer_init(&sbuf);
    msgpack_packer_init(&pck, &sbuf, msgpack_sbuffer_write);

    for (i = 0; i < arr_size ; i++) {
        t = &tokens[i];
        if (t->start == -1 || t->end == -1 || (t->start == 0 && t->end == 0)) {
            break;
        }
        flen = (t->end - t->start);

        switch (t->type) {
        case JSMN_OBJECT:
            flb_debug("json_pack: token=%i is OBJECT (size=%i)", i, t->size);
            msgpack_pack_map(&pck, t->size);
            break;
        case JSMN_ARRAY:
            flb_debug("json_pack: token=%i is ARRAY (size=%i)", i, t->size);
            msgpack_pack_array(&pck, t->size);
            break;
        case JSMN_STRING:
            flb_debug("json_pack: token=%i is STRING (len=%i)\n", i, flen);
            msgpack_pack_bin(&pck, flen);
            msgpack_pack_bin_body(&pck, js + t->start, flen);
            break;
        case JSMN_PRIMITIVE:
            p = js + t->start;
            if (strncmp(p, "false", 5) == 0) {
                flb_debug("json_pack: token=%i is FALSE", i);
                msgpack_pack_false(&pck);
            }
            else if (strncmp(p, "true", 4) == 0) {
                flb_debug("json_pack: token=%i is TRUE", i);
                msgpack_pack_true(&pck);
            }
            else if (strncmp(p, "null", 4) == 0) {
                flb_debug("json_pack: token=%i is NULL", i);
                msgpack_pack_nil(&pck);
            }
            else {
                flb_debug("json_pack: token=%i is INT64", i);
                msgpack_pack_int64(&pck, atol(p));
            }
            break;
        }
    }

    /* dump data back to a new buffer */
    *size = sbuf.size;
    buf = malloc(sbuf.size);
    memcpy(buf, sbuf.data, sbuf.size);
    msgpack_sbuffer_destroy(&sbuf);

    free(tokens);
    return buf;
}
Exemplo n.º 24
0
FLB_INLINE int flb_io_net_connect(struct flb_io_upstream *u,
                                  struct flb_thread *th)
{
    int fd;
    int ret;
    int error = 0;
    socklen_t len = sizeof(error);

    if (u->fd > 0) {
        close(u->fd);
    }

    /* Create the socket */
    fd = flb_net_socket_create(AF_INET, FLB_TRUE);
    if (fd == -1) {
        flb_error("[io] could not create socket");
        return -1;
    }
    u->fd = fd;

    /* Make the socket non-blocking */
    flb_net_socket_nonblocking(u->fd);

    /* Start the connection */
    ret = flb_net_tcp_fd_connect(fd, u->tcp_host, u->tcp_port);
    if (ret == -1) {
        if (errno == EINPROGRESS) {
            flb_debug("[upstream] connection in process");
        }
        else {
        }

        u->event.mask = MK_EVENT_EMPTY;
        u->event.status = MK_EVENT_NONE;
        u->thread = th;

        ret = mk_event_add(u->evl,
                           fd,
                           FLB_ENGINE_EV_THREAD,
                           MK_EVENT_WRITE, &u->event);
        if (ret == -1) {
            /*
             * If we failed here there no much that we can do, just
             * let the caller we failed
             */
            close(fd);
            return -1;
        }

        /*
         * Return the control to the parent caller, we need to wait for
         * the event loop to get back to us.
         */
        flb_thread_yield(th, FLB_FALSE);

        /* We got a notification, remove the event registered */
        ret = mk_event_del(u->evl, &u->event);
        assert(ret == 0);

        /* Check the connection status */
        if (u->event.mask & MK_EVENT_WRITE) {
            ret = getsockopt(fd, SOL_SOCKET, SO_ERROR, &error, &len);
            if (ret == -1) {
                flb_error("[io] could not validate socket status");
                return -1;
            }

            if (error != 0) {
                /* Connection is broken, not much to do here */
                flb_debug("[io] connection failed");
                return -1;
            }
            u->event.mask   = MK_EVENT_EMPTY;
            u->event.status = MK_EVENT_NONE;
        }
        else {
            return -1;
        }
    }

    flb_debug("[io] connection OK");
    return 0;
}
Exemplo n.º 25
0
void cb_forward_flush(void *data, size_t bytes,
                      char *tag, int tag_len,
                      struct flb_input_instance *i_ins, void *out_context,
                      struct flb_config *config)
{
    int ret = -1;
    int entries = 0;
    size_t off = 0;
    size_t total;
    size_t bytes_sent;
    msgpack_packer   mp_pck;
    msgpack_sbuffer  mp_sbuf;
    msgpack_unpacked result;
    struct flb_out_forward_config *ctx = out_context;
    struct flb_upstream_conn *u_conn;
    (void) i_ins;
    (void) config;

    flb_debug("[out_forward] request %lu bytes to flush", bytes);

    /* Initialize packager */
    msgpack_sbuffer_init(&mp_sbuf);
    msgpack_packer_init(&mp_pck, &mp_sbuf, msgpack_sbuffer_write);

    /* Count number of entries, is there a better way to do this ? */
    msgpack_unpacked_init(&result);
    while (msgpack_unpack_next(&result, data, bytes, &off)) {
        entries++;
    }
    flb_debug("[out_fw] %i entries tag='%s' tag_len=%i",
              entries, tag, tag_len);
    msgpack_unpacked_destroy(&result);

    /* Output: root array */
    msgpack_pack_array(&mp_pck, 2);
    msgpack_pack_str(&mp_pck, tag_len);
    msgpack_pack_str_body(&mp_pck, tag, tag_len);
    msgpack_pack_array(&mp_pck, entries);

    /* Get a TCP connection instance */
    u_conn = flb_upstream_conn_get(ctx->u);
    if (!u_conn) {
        flb_error("[out_forward] no upstream connections available");
        msgpack_sbuffer_destroy(&mp_sbuf);
        FLB_OUTPUT_RETURN(FLB_RETRY);
    }

    /* Write message header */
    ret = flb_io_net_write(u_conn, mp_sbuf.data, mp_sbuf.size, &bytes_sent);
    if (ret == -1) {
        flb_error("[out_forward] could not write chunk header");
        msgpack_sbuffer_destroy(&mp_sbuf);
        flb_upstream_conn_release(u_conn);
        FLB_OUTPUT_RETURN(FLB_RETRY);
    }

    msgpack_sbuffer_destroy(&mp_sbuf);
    total = ret;

    /* Write body */
    ret = flb_io_net_write(u_conn, data, bytes, &bytes_sent);
    if (ret == -1) {
        flb_error("[out_forward] error writing content body");
        flb_upstream_conn_release(u_conn);
        FLB_OUTPUT_RETURN(FLB_RETRY);
    }

    total += bytes_sent;
    flb_upstream_conn_release(u_conn);
    flb_trace("[out_forward] ended write()=%d bytes", total);

    FLB_OUTPUT_RETURN(FLB_OK);
}
Exemplo n.º 26
0
int cb_es_init(struct flb_output_instance *ins,
               struct flb_config *config,
               void *data)
{
    int io_type;
    char *tmp;
    struct flb_uri *uri = ins->host.uri;
    struct flb_uri_field *f_index = NULL;
    struct flb_uri_field *f_type = NULL;
    struct flb_out_es_config *ctx = NULL;
    struct flb_upstream *upstream;
    (void) data;

    if (uri) {
        if (uri->count >= 2) {
            f_index = flb_uri_get(uri, 0);
            f_type  = flb_uri_get(uri, 1);
        }
    }

    /* Get network configuration */
    if (!ins->host.name) {
        ins->host.name = flb_strdup("127.0.0.1");
    }

    if (ins->host.port == 0) {
        ins->host.port = 9200;
    }

    /* Allocate plugin context */
    ctx = flb_malloc(sizeof(struct flb_out_es_config));
    if (!ctx) {
        perror("malloc");
        return -1;
    }

    if (ins->use_tls == FLB_TRUE) {
        io_type = FLB_IO_TLS;
    }
    else {
        io_type = FLB_IO_TCP;
    }

    /* Prepare an upstream handler */
    upstream = flb_upstream_create(config,
                                   ins->host.name,
                                   ins->host.port,
                                   io_type,
                                   &ins->tls);
    if (!upstream) {
        flb_free(ctx);
        return -1;
    }


    /* Set the context */
    ctx->u = upstream;
    if (f_index) {
        ctx->index = f_index->value;
    }
    else {
        tmp = flb_output_get_property("index", ins);
        if (!tmp) {
            ctx->index = "fluentbit";
        }
        else {
            ctx->index = tmp;
        }
    }

    if (f_type) {
        ctx->type = f_type->value;
    }
    else {
        tmp = flb_output_get_property("type", ins);
        if (!tmp) {
            ctx->type = "test";
        }
        else {
            ctx->type = tmp;
        }
    }

    flb_debug("[es] host=%s port=%i index=%s type=%s",
              ins->host.name, ins->host.port,
              ctx->index, ctx->type);

    flb_output_set_context(ins, ctx);
    return 0;
}
Exemplo n.º 27
0
/* This routine is called from a co-routine thread */
FLB_INLINE int net_io_write(struct flb_thread *th, struct flb_io_upstream *u,
                            void *data, size_t len, size_t *out_len)
{
    int ret = 0;
    ssize_t bytes;
    size_t total = 0;

 retry:
    bytes = write(u->fd, data + total, len - total);
    flb_debug("[io] write(2)=%d", bytes);

    if (bytes == -1) {
        if (errno == EAGAIN) {
            return 0;
        }
        else {
            /* The connection routine may yield */
            flb_debug("[io] trying to reconnect");
            ret = flb_io_net_connect(u, th);
            if (ret == -1) {
                return -1;
            }

            /*
             * Reach here means the connection was successful, let's retry
             * to write(2).
             *
             * note: the flb_io_connect() uses asyncronous sockets, register
             * the file descriptor with the main event loop and yields until
             * the main event loop returns the control back (resume), doing a
             * 'retry' it's pretty safe.
             */
            goto retry;
        }
    }

    /* Update statistics */
    //flb_stats_update(out->stats_fd, ret, 0);

    /* Update counters */
    total += bytes;
    if (total < len) {
        if (u->event.status == MK_EVENT_NONE) {
            u->event.mask = MK_EVENT_EMPTY;
            u->thread = th;
            ret = mk_event_add(u->evl,
                               u->fd,
                               FLB_ENGINE_EV_THREAD,
                               MK_EVENT_WRITE, &u->event);
            if (ret == -1) {
                /*
                 * If we failed here there no much that we can do, just
                 * let the caller we failed
                 */
                close(u->fd);
                return -1;
            }
        }
        flb_thread_yield(th, MK_FALSE);
        goto retry;
    }

    if (u->event.status == MK_EVENT_REGISTERED) {
        /* We got a notification, remove the event registered */
        ret = mk_event_del(u->evl, &u->event);
        assert(ret == 0);
    }

    *out_len = total;
    return bytes;
}
Exemplo n.º 28
0
/* Callback triggered when some serial msgs are available */
int in_serial_collect(struct flb_config *config, void *in_context)
{
    int ret;
    int bytes;
    int available;
    int len;
    int hits;
    char *sep;
    char *buf;

    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--;
        }


        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 {
            /* Process and enqueue the received line */
            process_line(ctx->buf_data, ctx->buf_len, ctx);
            ctx->buf_len = 0;
        }

    }
}
Exemplo n.º 29
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;
}
Exemplo n.º 30
0
/*
 * This routine perform a TCP connection and the required TLS/SSL
 * handshake,
 */
FLB_INLINE int flb_io_net_tls_connect(struct flb_io_upstream *u,
                                      struct flb_thread *th)
{
    int fd;
    int ret;
    int error = 0;
    int flag;
    socklen_t len = sizeof(error);
    struct flb_tls_session *session;

    if (u->fd > 0) {
        close(u->fd);
    }

    /* Create the socket */
    fd = flb_net_socket_create(AF_INET, FLB_TRUE);
    if (fd == -1) {
        flb_error("[io] could not create socket");
        return -1;
    }
    u->fd = fd;

    /* Make the socket non-blocking */
    flb_net_socket_nonblocking(u->fd);

    /* Start the connection */
    ret = flb_net_tcp_fd_connect(fd, u->tcp_host, u->tcp_port);
    if (ret == -1) {
        if (errno == EINPROGRESS) {
            flb_debug("[upstream] connection in process");
        }
        else {
            close(u->fd);
            if (u->tls_session) {
                tls_session_destroy(u->tls_session);
                u->tls_session = NULL;
            }
            return -1;
        }

        MK_EVENT_NEW(&u->event);
        u->thread = th;

        ret = mk_event_add(u->evl,
                           fd,
                           FLB_ENGINE_EV_THREAD,
                           MK_EVENT_WRITE, &u->event);
        if (ret == -1) {
            /*
             * If we failed here there no much that we can do, just
             * let the caller we failed
             */
            flb_error("[io_tls] connect failed registering event");
            close(fd);
            return -1;
        }

        /*
         * Return the control to the parent caller, we need to wait for
         * the event loop to get back to us.
         */
        flb_thread_yield(th, FLB_FALSE);

        /* Check the connection status */
        if (u->event.mask & MK_EVENT_WRITE) {
            ret = getsockopt(fd, SOL_SOCKET, SO_ERROR, &error, &len);
            if (ret == -1) {
                flb_error("[io_tls] could not validate socket status");
                goto error;
            }

            if (error != 0) {
                /* Connection is broken, not much to do here */
                flb_error("[io_tls] connection failed");
                goto error;
            }
        }
        else {
            return -1;
        }
    }

    /* Configure TLS and prepare handshake */
    session = u->tls_session;
    mbedtls_ssl_set_bio(&session->ssl,
                        u,
                        mbedtls_net_send, mbedtls_net_recv, NULL);

 retry_handshake:
    ret = mbedtls_ssl_handshake(&session->ssl);

    if (ret != 0) {
        if (ret != MBEDTLS_ERR_SSL_WANT_READ &&
            ret !=  MBEDTLS_ERR_SSL_WANT_WRITE) {
            io_tls_error(ret);
            goto error;
        }

        if (ret == MBEDTLS_ERR_SSL_WANT_WRITE) {
            flag = MK_EVENT_WRITE;
        }
        else if (ret == MBEDTLS_ERR_SSL_WANT_READ) {
            flag = MK_EVENT_READ;
        }
        else {

        }

        /*
         * FIXME: if we need multiple reads we are invoking the same
         * system call multiple times.
         */
        ret = mk_event_add(u->evl,
                           u->event.fd,
                           FLB_ENGINE_EV_THREAD,
                           flag, &u->event);
        if (ret == -1) {
            goto error;
        }

        flb_thread_yield(th, FLB_FALSE);
        goto retry_handshake;
    }
    else {
        flb_debug("[io_tls] Handshake OK");
    }

    if (u->event.status == MK_EVENT_REGISTERED) {
        mk_event_del(u->evl, &u->event);
    }
    flb_debug("[io_tls] connection OK");
    return 0;

 error:
    if (u->event.status == MK_EVENT_REGISTERED) {
        mk_event_del(u->evl, &u->event);
    }

    return -1;
}