1 /* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 
3 /*  Fluent Bit
4  *  ==========
5  *  Copyright (C) 2019-2021 The Fluent Bit Authors
6  *  Copyright (C) 2015-2018 Treasure Data Inc.
7  *
8  *  Licensed under the Apache License, Version 2.0 (the "License");
9  *  you may not use this file except in compliance with the License.
10  *  You may obtain a copy of the License at
11  *
12  *      http://www.apache.org/licenses/LICENSE-2.0
13  *
14  *  Unless required by applicable law or agreed to in writing, software
15  *  distributed under the License is distributed on an "AS IS" BASIS,
16  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  *  See the License for the specific language governing permissions and
18  *  limitations under the License.
19  */
20 
21 #include <fluent-bit/flb_input_plugin.h>
22 #include <fluent-bit/flb_config.h>
23 #include <fluent-bit/flb_error.h>
24 #include <fluent-bit/flb_pack.h>
25 #include <fluent-bit/flb_random.h>
26 #include <msgpack.h>
27 
28 #include <stdio.h>
29 #include <stdlib.h>
30 #include <sys/types.h>
31 #include <sys/stat.h>
32 #include <fcntl.h>
33 
34 #define DEFAULT_INTERVAL_SEC  1
35 #define DEFAULT_INTERVAL_NSEC 0
36 
37 struct flb_in_random_config {
38     /* Config properties */
39     int              interval_sec;
40     int              interval_nsec;
41     int              samples;
42 
43     /* Internal */
44     int              samples_count;
45 
46     struct flb_input_instance *ins;
47 };
48 
49 /* cb_collect callback */
in_random_collect(struct flb_input_instance * ins,struct flb_config * config,void * in_context)50 static int in_random_collect(struct flb_input_instance *ins,
51                              struct flb_config *config, void *in_context)
52 {
53     uint64_t val;
54     msgpack_packer mp_pck;
55     msgpack_sbuffer mp_sbuf;
56     struct flb_in_random_config *ctx = in_context;
57 
58     if (ctx->samples == 0) {
59         return -1;
60     }
61 
62     if (ctx->samples > 0 && (ctx->samples_count >= ctx->samples)) {
63         return -1;
64     }
65 
66     if (flb_random_bytes((unsigned char *) &val, sizeof(uint64_t))) {
67         val = time(NULL);
68     }
69 
70     /* Initialize local msgpack buffer */
71     msgpack_sbuffer_init(&mp_sbuf);
72     msgpack_packer_init(&mp_pck, &mp_sbuf, msgpack_sbuffer_write);
73 
74     /* Pack data */
75     msgpack_pack_array(&mp_pck, 2);
76     flb_pack_time_now(&mp_pck);
77     msgpack_pack_map(&mp_pck, 1);
78 
79     msgpack_pack_str(&mp_pck, 10);
80     msgpack_pack_str_body(&mp_pck, "rand_value", 10);
81     msgpack_pack_uint64(&mp_pck, val);
82 
83     flb_input_chunk_append_raw(ins, NULL, 0, mp_sbuf.data, mp_sbuf.size);
84     msgpack_sbuffer_destroy(&mp_sbuf);
85     ctx->samples_count++;
86 
87     return 0;
88 }
89 
90 /* Set plugin configuration */
in_random_config_read(struct flb_in_random_config * ctx,struct flb_input_instance * in)91 static int in_random_config_read(struct flb_in_random_config *ctx,
92                                  struct flb_input_instance *in)
93 {
94     const char *val = NULL;
95 
96     /* samples */
97     val = flb_input_get_property("samples", in);
98     if (val != NULL && atoi(val) >= 0) {
99         ctx->samples = atoi(val);
100     }
101 
102     /* interval settings */
103     val = flb_input_get_property("interval_sec", in);
104     if (val != NULL && atoi(val) >= 0) {
105         ctx->interval_sec = atoi(val);
106     }
107     else {
108         ctx->interval_sec = DEFAULT_INTERVAL_SEC;
109     }
110 
111     val = flb_input_get_property("interval_nsec", in);
112     if (val != NULL && atoi(val) >= 0) {
113         ctx->interval_nsec = atoi(val);
114     }
115     else {
116         ctx->interval_nsec = DEFAULT_INTERVAL_NSEC;
117     }
118 
119     if (ctx->interval_sec <= 0 && ctx->interval_nsec <= 0) {
120         /* Illegal settings. Override them. */
121         ctx->interval_sec = DEFAULT_INTERVAL_SEC;
122         ctx->interval_nsec = DEFAULT_INTERVAL_NSEC;
123     }
124 
125 
126     flb_plg_debug(ctx->ins, "interval_sec=%d interval_nsec=%d",
127                   ctx->interval_sec, ctx->interval_nsec);
128 
129     return 0;
130 }
131 
132 /* Initialize plugin */
in_random_init(struct flb_input_instance * in,struct flb_config * config,void * data)133 static int in_random_init(struct flb_input_instance *in,
134                         struct flb_config *config, void *data)
135 {
136     int ret = -1;
137     struct flb_in_random_config *ctx = NULL;
138 
139     /* Allocate space for the configuration */
140     ctx = flb_malloc(sizeof(struct flb_in_random_config));
141     if (!ctx) {
142         return -1;
143     }
144     ctx->samples       = -1;
145     ctx->samples_count = 0;
146     ctx->ins = in;
147 
148     /* Initialize head config */
149     ret = in_random_config_read(ctx, in);
150     if (ret < 0) {
151         flb_free(ctx);
152         return -1;
153     }
154 
155     flb_input_set_context(in, ctx);
156     ret = flb_input_set_collector_time(in,
157                                        in_random_collect,
158                                        ctx->interval_sec,
159                                        ctx->interval_nsec, config);
160     if (ret < 0) {
161         flb_plg_error(ctx->ins, "could not set collector for head input plugin");
162         flb_free(ctx);
163         return -1;
164     }
165 
166     return 0;
167 }
168 
in_random_exit(void * data,struct flb_config * config)169 static int in_random_exit(void *data, struct flb_config *config)
170 {
171     (void) *config;
172     struct flb_in_random_config *ctx = data;
173 
174     if (!ctx) {
175         return 0;
176     }
177 
178     flb_free(ctx);
179     return 0;
180 }
181 
182 
183 struct flb_input_plugin in_random_plugin = {
184     .name         = "random",
185     .description  = "Random",
186     .cb_init      = in_random_init,
187     .cb_pre_run   = NULL,
188     .cb_collect   = in_random_collect,
189     .cb_flush_buf = NULL,
190     .cb_exit      = in_random_exit
191 };
192