code cleanup
Costa Tsaousis (ktsaou) committed
Nov 22, 2015 at 14:16 UTC
c55bc3e5029e74a8dc99bd95faee5eceb2021081
6 files changed
+195
-153
README.md
+3
-1
@@ -17,7 +17,9 @@ Check it live at:
17
18
Here is a screenshot:
19
20
-
20
+
21
+
22
+
23
24
25
# Features
src/appconfig.c
+7
-12
@@ -359,10 +359,9 @@ void generate_config(struct web_buffer *wb, int only_changed)
359
struct config_value *cv;
360
361
for(i = 0; i < 3 ;i++) {
362
- web_buffer_increase(wb, 500);
362
switch(i) {
363
case 0:
365
- web_buffer_printf(wb,
364
+ web_buffer_strcat(wb,
365
"# NetData Configuration\n"
366
"# You can uncomment and change any of the options below.\n"
367
"# The value shown in the commented settings, is the default value.\n"
@@ -370,11 +369,11 @@ void generate_config(struct web_buffer *wb, int only_changed)
369
break;
370
371
case 1:
373
- web_buffer_printf(wb, "\n\n# per plugin configuration\n");
372
+ web_buffer_strcat(wb, "\n\n# per plugin configuration\n");
373
break;
374
375
case 2:
377
- web_buffer_printf(wb, "\n\n# per chart configuration\n");
376
+ web_buffer_strcat(wb, "\n\n# per chart configuration\n");
377
break;
378
}
379
@@ -397,21 +396,17 @@ void generate_config(struct web_buffer *wb, int only_changed)
396
if(only_changed && !changed) continue;
397
398
if(!used) {
400
- web_buffer_increase(wb, 500);
401
- web_buffer_printf(wb, "\n# node '%s' is not used.", co->name);
399
+ web_buffer_snprintf(wb, CONFIG_FILE_LINE_MAX+1, "\n# node '%s' is not used.", co->name);
400
}
401
404
- web_buffer_increase(wb, CONFIG_FILE_LINE_MAX+1);
405
- web_buffer_printf(wb, "\n[%s]\n", co->name);
402
+ web_buffer_snprintf(wb, CONFIG_FILE_LINE_MAX+1, "\n[%s]\n", co->name);
403
404
for(cv = co->values; cv ; cv = cv->next) {
405
406
if(used && !(cv->flags & CONFIG_VALUE_USED)) {
410
- web_buffer_increase(wb, CONFIG_FILE_LINE_MAX + 1);
411
- web_buffer_printf(wb, "\n\t# option '%s' is not used.\n", cv->name);
407
+ web_buffer_snprintf(wb, CONFIG_FILE_LINE_MAX + 1, "\n\t# option '%s' is not used.\n", cv->name);
408
}
413
- web_buffer_increase(wb, CONFIG_FILE_LINE_MAX + 1);
414
- web_buffer_printf(wb, "\t%s%s = %s\n", ((!(cv->flags & CONFIG_VALUE_CHANGED)) && (cv->flags & CONFIG_VALUE_USED))?"# ":"", cv->name, cv->value);
409
+ web_buffer_snprintf(wb, CONFIG_FILE_LINE_MAX + 1, "\t%s%s = %s\n", ((!(cv->flags & CONFIG_VALUE_CHANGED)) && (cv->flags & CONFIG_VALUE_USED))?"# ":"", cv->name, cv->value);
410
}
411
}
412
}
src/rrd2json.c
+35
-43
@@ -15,11 +15,10 @@ char *hostname = "unknown";
15
unsigned long rrd_stats_one_json(RRDSET *st, char *options, struct web_buffer *wb)
16
{
17
time_t now = time(NULL);
18
- web_buffer_increase(wb, 65536);
18
19
pthread_rwlock_rdlock(&st->rwlock);
20
22
- web_buffer_printf(wb,
21
+ web_buffer_snprintf(wb, 65536,
22
"\t\t{\n"
23
"\t\t\t\"id\": \"%s\",\n"
24
"\t\t\t\"name\": \"%s\",\n"
@@ -70,11 +69,10 @@ unsigned long rrd_stats_one_json(RRDSET *st, char *options, struct web_buffer *w
69
70
RRDDIM *rd;
71
for(rd = st->dimensions; rd ; rd = rd->next) {
73
- web_buffer_increase(wb, 4096);
72
73
memory += rd->memsize;
74
77
- web_buffer_printf(wb,
75
+ web_buffer_snprintf(wb, 4096,
76
"\t\t\t\t{\n"
77
"\t\t\t\t\t\"id\": \"%s\",\n"
78
"\t\t\t\t\t\"name\": \"%s\",\n"
@@ -107,7 +105,7 @@ unsigned long rrd_stats_one_json(RRDSET *st, char *options, struct web_buffer *w
105
);
106
}
107
110
- web_buffer_printf(wb,
108
+ web_buffer_snprintf(wb, 200,
109
"\t\t\t],\n"
110
"\t\t\t\"memory\" : %lu\n"
111
"\t\t}"
@@ -123,34 +121,30 @@ unsigned long rrd_stats_one_json(RRDSET *st, char *options, struct web_buffer *w
121
122
void rrd_stats_graph_json(RRDSET *st, char *options, struct web_buffer *wb)
123
{
126
- web_buffer_increase(wb, 2048);
127
-
128
- web_buffer_printf(wb, RRD_GRAPH_JSON_HEADER);
124
+ web_buffer_snprintf(wb, sizeof(RRD_GRAPH_JSON_HEADER), RRD_GRAPH_JSON_HEADER);
125
rrd_stats_one_json(st, options, wb);
130
- web_buffer_printf(wb, RRD_GRAPH_JSON_FOOTER);
126
+ web_buffer_snprintf(wb, sizeof(RRD_GRAPH_JSON_FOOTER), RRD_GRAPH_JSON_FOOTER);
127
}
128
129
void rrd_stats_all_json(struct web_buffer *wb)
130
{
135
- web_buffer_increase(wb, 2048);
136
-
131
unsigned long memory = 0;
132
long c;
133
RRDSET *st;
134
141
- web_buffer_printf(wb, RRD_GRAPH_JSON_HEADER);
135
+ web_buffer_snprintf(wb, sizeof(RRD_GRAPH_JSON_HEADER), RRD_GRAPH_JSON_HEADER);
136
137
pthread_rwlock_rdlock(&rrdset_root_rwlock);
138
for(st = rrdset_root, c = 0; st ; st = st->next) {
139
if(st->enabled) {
146
- if(c) web_buffer_printf(wb, "%s", ",\n");
140
+ if(c) web_buffer_strcat(wb, ",\n");
141
memory += rrd_stats_one_json(st, NULL, wb);
142
c++;
143
}
144
}
145
pthread_rwlock_unlock(&rrdset_root_rwlock);
146
153
- web_buffer_printf(wb, "\n\t],\n"
147
+ web_buffer_snprintf(wb, 4096, "\n\t],\n"
148
"\t\"hostname\": \"%s\",\n"
149
"\t\"update_every\": %d,\n"
150
"\t\"history\": %d,\n"
@@ -379,7 +373,8 @@ RRDR *rrd2rrdr(RRDSET *st, long points, time_t after, time_t before, int group_m
373
if(duration <= 0) return NULL;
374
375
// check the required points
382
- if(points <= 0) points = duration;
376
+ if(points > duration / st->update_every) points = 0;
377
+ if(points <= 0) points = duration / st->update_every;
378
379
// calculate proper grouping of source data
380
long group = duration / points;
@@ -622,7 +617,7 @@ unsigned long rrd_stats_json(int type, RRDSET *st, struct web_buffer *wb, int po
617
for( rd = st->dimensions ; rd ; rd = rd->next) dimensions++;
618
if(!dimensions) {
619
pthread_rwlock_unlock(&st->rwlock);
625
- web_buffer_printf(wb, "No dimensions yet.");
620
+ web_buffer_strcat(wb, "No dimensions yet.");
621
return 0;
622
}
623
@@ -694,10 +689,10 @@ unsigned long rrd_stats_json(int type, RRDSET *st, struct web_buffer *wb, int po
689
// -------------------------------------------------------------------------
690
// print the JSON header
691
697
- web_buffer_printf(wb, "{\n %scols%s:\n [\n", kq, kq);
698
- web_buffer_printf(wb, " {%sid%s:%s%s,%slabel%s:%stime%s,%spattern%s:%s%s,%stype%s:%sdatetime%s},\n", kq, kq, sq, sq, kq, kq, sq, sq, kq, kq, sq, sq, kq, kq, sq, sq);
699
- web_buffer_printf(wb, " {%sid%s:%s%s,%slabel%s:%s%s,%spattern%s:%s%s,%stype%s:%sstring%s,%sp%s:{%srole%s:%sannotation%s}},\n", kq, kq, sq, sq, kq, kq, sq, sq, kq, kq, sq, sq, kq, kq, sq, sq, kq, kq, kq, kq, sq, sq);
700
- web_buffer_printf(wb, " {%sid%s:%s%s,%slabel%s:%s%s,%spattern%s:%s%s,%stype%s:%sstring%s,%sp%s:{%srole%s:%sannotationText%s}}", kq, kq, sq, sq, kq, kq, sq, sq, kq, kq, sq, sq, kq, kq, sq, sq, kq, kq, kq, kq, sq, sq);
692
+ web_buffer_snprintf(wb, 1024, "{\n %scols%s:\n [\n", kq, kq);
693
+ web_buffer_snprintf(wb, 1024, " {%sid%s:%s%s,%slabel%s:%stime%s,%spattern%s:%s%s,%stype%s:%sdatetime%s},\n", kq, kq, sq, sq, kq, kq, sq, sq, kq, kq, sq, sq, kq, kq, sq, sq);
694
+ web_buffer_snprintf(wb, 1024, " {%sid%s:%s%s,%slabel%s:%s%s,%spattern%s:%s%s,%stype%s:%sstring%s,%sp%s:{%srole%s:%sannotation%s}},\n", kq, kq, sq, sq, kq, kq, sq, sq, kq, kq, sq, sq, kq, kq, sq, sq, kq, kq, kq, kq, sq, sq);
695
+ web_buffer_snprintf(wb, 1024, " {%sid%s:%s%s,%slabel%s:%s%s,%spattern%s:%s%s,%stype%s:%sstring%s,%sp%s:{%srole%s:%sannotationText%s}}", kq, kq, sq, sq, kq, kq, sq, sq, kq, kq, sq, sq, kq, kq, sq, sq, kq, kq, kq, kq, sq, sq);
696
697
// print the header for each dimension
698
// and update the print_hidden array for the dimensions that should be hidden
@@ -705,15 +700,15 @@ unsigned long rrd_stats_json(int type, RRDSET *st, struct web_buffer *wb, int po
700
for( rd = st->dimensions, c = 0 ; rd && c < dimensions ; rd = rd->next, c++) {
701
if(!print_hidden[c]) {
702
pc++;
708
- web_buffer_printf(wb, ",\n {%sid%s:%s%s,%slabel%s:%s%s%s,%spattern%s:%s%s,%stype%s:%snumber%s}", kq, kq, sq, sq, kq, kq, sq, rd->name, sq, kq, kq, sq, sq, kq, kq, sq, sq);
703
+ web_buffer_snprintf(wb, 1024, ",\n {%sid%s:%s%s,%slabel%s:%s%s%s,%spattern%s:%s%s,%stype%s:%snumber%s}", kq, kq, sq, sq, kq, kq, sq, rd->name, sq, kq, kq, sq, sq, kq, kq, sq, sq);
704
}
705
}
706
if(!pc) {
712
- web_buffer_printf(wb, ",\n {%sid%s:%s%s,%slabel%s:%s%s%s,%spattern%s:%s%s,%stype%s:%snumber%s}", kq, kq, sq, sq, kq, kq, sq, "no data", sq, kq, kq, sq, sq, kq, kq, sq, sq);
707
+ web_buffer_snprintf(wb, 1024, ",\n {%sid%s:%s%s,%slabel%s:%s%s%s,%spattern%s:%s%s,%stype%s:%snumber%s}", kq, kq, sq, sq, kq, kq, sq, "no data", sq, kq, kq, sq, sq, kq, kq, sq, sq);
708
}
709
710
// print the begin of row data
716
- web_buffer_printf(wb, "\n ],\n %srows%s:\n [\n", kq, kq);
711
+ web_buffer_snprintf(wb, 1024, "\n ],\n %srows%s:\n [\n", kq, kq);
712
713
714
// -------------------------------------------------------------------------
@@ -785,18 +780,15 @@ unsigned long rrd_stats_json(int type, RRDSET *st, struct web_buffer *wb, int po
780
break;
781
}
782
788
- // check if we may exceed the buffer provided
789
- web_buffer_increase(wb, line_size);
790
-
783
// generate the local date time
784
struct tm *tm = localtime(&now);
785
if(!tm) { error("localtime() failed."); continue; }
786
if(now > last_timestamp) last_timestamp = now;
787
796
- if(printed) web_buffer_strcpy(wb, "]},\n");
797
- web_buffer_strcpy(wb, pre_date);
788
+ if(printed) web_buffer_strcat(wb, "]},\n");
789
+ web_buffer_strcat(wb, pre_date);
790
web_buffer_jsdate(wb, tm->tm_year + 1900, tm->tm_mon, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec);
799
- web_buffer_strcpy(wb, post_date);
791
+ web_buffer_strcat(wb, post_date);
792
793
print_this = 1;
794
}
@@ -832,26 +824,26 @@ unsigned long rrd_stats_json(int type, RRDSET *st, struct web_buffer *wb, int po
824
if(print_this) {
825
if(annotate_reset) {
826
annotation_count++;
835
- web_buffer_strcpy(wb, overflow_annotation);
827
+ web_buffer_strcat(wb, overflow_annotation);
828
annotate_reset = 0;
829
}
830
else
839
- web_buffer_strcpy(wb, normal_annotation);
831
+ web_buffer_strcat(wb, normal_annotation);
832
833
pc = 0;
834
for(c = 0 ; c < dimensions ; c++) {
835
if(found_non_existing[c] == group_count) {
836
// all entries are non-existing
837
pc++;
846
- web_buffer_strcpy(wb, pre_value);
847
- web_buffer_strcpy(wb, "null");
848
- web_buffer_strcpy(wb, post_value);
838
+ web_buffer_strcat(wb, pre_value);
839
+ web_buffer_strcat(wb, "null");
840
+ web_buffer_strcat(wb, post_value);
841
}
842
else if(!print_hidden[c]) {
843
pc++;
852
- web_buffer_strcpy(wb, pre_value);
844
+ web_buffer_strcat(wb, pre_value);
845
web_buffer_rrd_value(wb, group_values[c]);
854
- web_buffer_strcpy(wb, post_value);
846
+ web_buffer_strcat(wb, post_value);
847
848
if(group_values[c]) found_non_zero[c]++;
849
}
@@ -863,9 +855,9 @@ unsigned long rrd_stats_json(int type, RRDSET *st, struct web_buffer *wb, int po
855
856
// if all dimensions are hidden, print a null
857
if(!pc) {
866
- web_buffer_strcpy(wb, pre_value);
867
- web_buffer_strcpy(wb, "null");
868
- web_buffer_strcpy(wb, post_value);
858
+ web_buffer_strcat(wb, pre_value);
859
+ web_buffer_strcat(wb, "null");
860
+ web_buffer_strcat(wb, post_value);
861
}
862
863
printed++;
@@ -873,8 +865,8 @@ unsigned long rrd_stats_json(int type, RRDSET *st, struct web_buffer *wb, int po
865
}
866
}
867
876
- if(printed) web_buffer_printf(wb, "]}");
877
- web_buffer_printf(wb, "\n ]\n}\n");
868
+ if(printed) web_buffer_strcat(wb, "]}");
869
+ web_buffer_strcat(wb, "\n ]\n}\n");
870
871
if(only_non_zero && max_loop > 1) {
872
int changed = 0;
@@ -888,14 +880,14 @@ unsigned long rrd_stats_json(int type, RRDSET *st, struct web_buffer *wb, int po
880
}
881
}
882
891
- if(changed) web_buffer_reset(wb);
883
+ if(changed) web_buffer_flush(wb);
884
else break;
885
}
886
else break;
887
888
} // max_loop
889
898
- debug(D_RRD_STATS, "RRD_STATS_JSON: %s total %ld bytes", st->name, wb->bytes);
890
+ debug(D_RRD_STATS, "RRD_STATS_JSON: %s total %ld bytes", st->name, wb->len);
891
892
pthread_rwlock_unlock(&st->rwlock);
893
return last_timestamp;
src/web_buffer.c
+68
-11
@@ -2,6 +2,7 @@
2
#include <config.h>
3
#endif
4
#include <stdlib.h>
5
+#include <string.h>
6
7
#ifdef STORAGE_WITH_MATH
8
#include <math.h>
@@ -11,21 +12,72 @@
12
#include "web_buffer.h"
13
#include "log.h"
14
14
-void web_buffer_strcpy(struct web_buffer *wb, const char *txt)
15
+void web_buffer_reset(struct web_buffer *wb)
16
+{
17
+ web_buffer_flush(wb);
18
+
19
+ wb->sent = 0;
20
+ wb->rlen = 0;
21
+ wb->contenttype = CT_TEXT_PLAIN;
22
+ wb->date = 0;
23
+}
24
+
25
+void web_buffer_char_replace(struct web_buffer *wb, char from, char to)
26
+{
27
+ char *s = wb->buffer, *end = &wb->buffer[wb->len];
28
+
29
+ while(s != end) {
30
+ if(*s == from) *s = to;
31
+ s++;
32
+ }
33
+}
34
+
35
+
36
+void web_buffer_strcat(struct web_buffer *wb, const char *txt)
37
{
38
char *buffer = wb->buffer;
17
- long bytes = wb->bytes, size = wb->size, i = 0;
39
+ const char *s = txt;
40
+ long bytes = wb->len, size = wb->size;
41
+
42
+ while(*s && bytes < size)
43
+ buffer[bytes++] = *s++;
44
19
- while(txt[i] && bytes < size)
20
- buffer[bytes++] = txt[i++];
45
+ wb->len = bytes;
46
22
- wb->bytes = bytes;
47
+ if(*s) {
48
+ web_buffer_need_bytes(wb, strlen(s));
49
+ web_buffer_strcat(wb, s);
50
+ }
51
+ else {
52
+ // terminate the string
53
+ // without increasing the length
54
+ web_buffer_need_bytes(wb, 1);
55
+ wb->buffer[wb->len] = '\0';
56
+ }
57
}
58
59
+
60
+void web_buffer_snprintf(struct web_buffer *wb, size_t len, const char *fmt, ...)
61
+{
62
+ web_buffer_need_bytes(wb, len+1);
63
+
64
+ va_list args;
65
+ va_start(args, fmt);
66
+ wb->len += vsnprintf(&wb->buffer[wb->len], len+1, fmt, args);
67
+ va_end(args);
68
+
69
+ // the buffer is \0 terminated by vsnprintf
70
+}
71
+
72
+
73
void web_buffer_rrd_value(struct web_buffer *wb, calculated_number value)
74
{
27
- if(wb->size - wb->bytes < 50) return;
28
- wb->bytes += print_calculated_number(&wb->buffer[wb->bytes], value);
75
+ web_buffer_need_bytes(wb, 50);
76
+ wb->len += print_calculated_number(&wb->buffer[wb->len], value);
77
+
78
+ // terminate it
79
+ web_buffer_need_bytes(wb, 1);
80
+ wb->buffer[wb->len] = '\0';
81
}
82
83
// generate a javascript date, the fastest possible way...
@@ -35,9 +87,9 @@ void web_buffer_jsdate(struct web_buffer *wb, int year, int month, int day, int
87
// 01234567890123456789012345678901234
88
// Date(2014, 04, 01, 03, 28, 20, 065)
89
38
- if(wb->size - wb->bytes < 36) return;
90
+ web_buffer_need_bytes(wb, 36);
91
40
- char *b = &wb->buffer[wb->bytes];
92
+ char *b = &wb->buffer[wb->len];
93
94
int i = 0;
95
b[i++]='D';
@@ -72,7 +124,11 @@ void web_buffer_jsdate(struct web_buffer *wb, int year, int month, int day, int
124
b[i++]=')';
125
b[i]='\0';
126
75
- wb->bytes += i;
127
+ wb->len += i;
128
+
129
+ // terminate it
130
+ web_buffer_need_bytes(wb, 1);
131
+ wb->buffer[wb->len] = '\0';
132
}
133
134
struct web_buffer *web_buffer_create(long size)
@@ -109,9 +165,10 @@ void web_buffer_free(struct web_buffer *b)
165
166
void web_buffer_increase(struct web_buffer *b, long free_size_required)
167
{
112
- long left = b->size - b->bytes;
168
+ long left = b->size - b->len;
169
170
if(left >= free_size_required) return;
171
+
172
long increase = free_size_required - left;
173
if(increase < WEB_DATA_LENGTH_INCREASE_STEP) increase = WEB_DATA_LENGTH_INCREASE_STEP;
174
src/web_buffer.h
+11
-5
@@ -9,11 +9,11 @@
9
10
struct web_buffer {
11
long size; // allocation size of buffer
12
- long bytes; // current data length in buffer
12
+ long len; // current data length in buffer
13
long sent; // current data length sent to output
14
char *buffer; // the buffer
15
int contenttype;
16
- long rbytes; // if non-zero, the excepted size of ifd
16
+ long rlen; // if non-zero, the excepted size of ifd
17
time_t date; // the date this content has been generated
18
};
19
@@ -33,10 +33,12 @@ struct web_buffer {
33
#define CT_APPLICATION_VND_MS_FONTOBJ 13
34
#define CT_IMAGE_SVG_XML 14
35
36
-#define web_buffer_printf(wb, args...) wb->bytes += snprintf(&wb->buffer[wb->bytes], (wb->size - wb->bytes), ##args)
37
-#define web_buffer_reset(wb) wb->buffer[wb->bytes = 0] = '\0'
36
+#define web_buffer_need_bytes(buffer, needed_free_size) do { if(unlikely((buffer)->size - (buffer)->len < (needed_free_size))) web_buffer_increase((buffer), (needed_free_size)); } while(0)
37
39
-void web_buffer_strcpy(struct web_buffer *wb, const char *txt);
38
+#define web_buffer_flush(wb) wb->buffer[wb->len = 0] = '\0'
39
+void web_buffer_reset(struct web_buffer *wb);
40
+
41
+void web_buffer_strcat(struct web_buffer *wb, const char *txt);
42
void web_buffer_rrd_value(struct web_buffer *wb, calculated_number value);
43
44
void web_buffer_jsdate(struct web_buffer *wb, int year, int month, int day, int hours, int minutes, int seconds);
@@ -45,4 +47,8 @@ struct web_buffer *web_buffer_create(long size);
47
void web_buffer_free(struct web_buffer *b);
48
void web_buffer_increase(struct web_buffer *b, long free_size_required);
49
50
+void web_buffer_snprintf(struct web_buffer *wb, size_t len, const char *fmt, ...);
51
+
52
+void web_buffer_char_replace(struct web_buffer *wb, char from, char to);
53
+
54
#endif /* NETDATA_WEB_BUFFER_H */
src/web_client.c
+71
-81
@@ -152,7 +152,7 @@ int mysendfile(struct web_client *w, char *filename)
152
// if the filename contains a / or a .., refuse to serve it
153
if(strchr(filename, '/') != 0 || strstr(filename, "..") != 0) {
154
debug(D_WEB_CLIENT_ACCESS, "%llu: File '%s' is not acceptable.", w->id, filename);
155
- web_buffer_printf(w->data, "File '%s' cannot be served. Filenames cannot contain / or ..", filename);
155
+ web_buffer_snprintf(w->data, FILENAME_MAX + 1024, "File '%s' cannot be served. Filenames cannot contain / or ..", filename);
156
return 400;
157
}
158
@@ -164,14 +164,14 @@ int mysendfile(struct web_client *w, char *filename)
164
struct stat stat;
165
if(lstat(webfilename, &stat) != 0) {
166
error("%llu: File '%s' is not found.", w->id, webfilename);
167
- web_buffer_printf(w->data, "File '%s' does not exist, or is not accessible.", filename);
167
+ web_buffer_snprintf(w->data, FILENAME_MAX + 1024, "File '%s' does not exist, or is not accessible.", filename);
168
return 404;
169
}
170
171
// check if the file is owned by us
172
if(stat.st_uid != getuid() && stat.st_uid != geteuid()) {
173
error("%llu: File '%s' is owned by user %d (I run as user %d). Access Denied.", w->id, webfilename, stat.st_uid, getuid());
174
- web_buffer_printf(w->data, "Access to file '%s' is not permitted.", filename);
174
+ web_buffer_snprintf(w->data, FILENAME_MAX + 1024, "Access to file '%s' is not permitted.", filename);
175
return 403;
176
}
177
@@ -183,12 +183,12 @@ int mysendfile(struct web_client *w, char *filename)
183
if(errno == EBUSY || errno == EAGAIN) {
184
error("%llu: File '%s' is busy, sending 307 Moved Temporarily to force retry.", w->id, webfilename);
185
snprintf(w->response_header, MAX_HTTP_HEADER_SIZE, "Location: /" WEB_PATH_FILE "/%s\r\n", filename);
186
- web_buffer_printf(w->data, "The file '%s' is currently busy. Please try again later.", filename);
186
+ web_buffer_snprintf(w->data, FILENAME_MAX + 1024, "The file '%s' is currently busy. Please try again later.", filename);
187
return 307;
188
}
189
else {
190
error("%llu: Cannot open file '%s'.", w->id, webfilename);
191
- web_buffer_printf(w->data, "Cannot open file '%s'.", filename);
191
+ web_buffer_snprintf(w->data, FILENAME_MAX + 1024, "Cannot open file '%s'.", filename);
192
return 404;
193
}
194
}
@@ -212,9 +212,8 @@ int mysendfile(struct web_client *w, char *filename)
212
w->mode = WEB_CLIENT_MODE_FILECOPY;
213
w->wait_receive = 1;
214
w->wait_send = 0;
215
- w->data->bytes = 0;
216
- w->data->buffer[0] = '\0';
217
- w->data->rbytes = stat.st_size;
215
+ web_buffer_flush(w->data);
216
+ w->data->rlen = stat.st_size;
217
w->data->date = stat.st_mtim.tv_sec;
218
219
return 200;
@@ -225,13 +224,13 @@ void web_client_reset(struct web_client *w)
224
struct timeval tv;
225
gettimeofday(&tv, NULL);
226
228
- long sent = (w->mode == WEB_CLIENT_MODE_FILECOPY)?w->data->rbytes:w->data->bytes;
227
+ long sent = (w->mode == WEB_CLIENT_MODE_FILECOPY)?w->data->rlen:w->data->len;
228
229
#ifdef NETDATA_WITH_ZLIB
230
if(likely(w->zoutput)) sent = (long)w->zstream.total_out;
231
#endif
232
234
- long size = (w->mode == WEB_CLIENT_MODE_FILECOPY)?w->data->rbytes:w->data->bytes;
233
+ long size = (w->mode == WEB_CLIENT_MODE_FILECOPY)?w->data->rlen:w->data->len;
234
235
if(likely(w->last_url[0]))
236
log_access("%llu: (sent/all = %ld/%ld bytes %0.0f%%, prep/sent/total = %0.2f/%0.2f/%0.2f ms) %s: '%s'",
@@ -254,15 +253,11 @@ void web_client_reset(struct web_client *w)
253
254
w->last_url[0] = '\0';
255
257
- w->data->contenttype = CT_TEXT_PLAIN;
256
w->mode = WEB_CLIENT_MODE_NORMAL;
257
260
- w->data->rbytes = 0;
261
- w->data->bytes = 0;
262
- w->data->sent = 0;
263
-
258
w->response_header[0] = '\0';
265
- w->data->buffer[0] = '\0';
259
+
260
+ web_buffer_reset(w->data);
261
262
w->wait_receive = 1;
263
w->wait_send = 0;
@@ -350,7 +345,7 @@ int web_client_data_request(struct web_client *w, char *url, int datasource_type
345
if(!st) {
346
// we don't have it
347
// try to send a file with that name
353
- w->data->bytes = 0;
348
+ web_buffer_flush(w->data);
349
return(mysendfile(w, tok));
350
}
351
@@ -404,7 +399,7 @@ int web_client_data_request(struct web_client *w, char *url, int datasource_type
399
}
400
401
w->data->contenttype = CT_APPLICATION_JSON;
407
- w->data->bytes = 0;
402
+ web_buffer_flush(w->data);
403
404
char *google_version = "0.6";
405
char *google_reqId = "0";
@@ -456,7 +451,7 @@ int web_client_data_request(struct web_client *w, char *url, int datasource_type
451
452
// check the client wants json
453
if(strcmp(google_out, "json") != 0) {
459
- w->data->bytes = snprintf(w->data->buffer, w->data->size,
454
+ web_buffer_snprintf(w->data, 65536,
455
"%s({version:'%s',reqId:'%s',status:'error',errors:[{reason:'invalid_query',message:'output format is not supported',detailed_message:'the format %s requested is not supported by netdata.'}]});",
456
google_responseHandler, google_version, google_reqId, google_out);
457
return 200;
@@ -465,7 +460,7 @@ int web_client_data_request(struct web_client *w, char *url, int datasource_type
460
}
461
462
if(datasource_type == DATASOURCE_GOOGLE_JSONP) {
468
- w->data->bytes = snprintf(w->data->buffer, w->data->size,
463
+ web_buffer_snprintf(w->data, 65536,
464
"%s({version:'%s',reqId:'%s',status:'ok',sig:'%lu',table:",
465
google_responseHandler, google_version, google_reqId, st->last_updated.tv_sec);
466
}
@@ -475,11 +470,11 @@ int web_client_data_request(struct web_client *w, char *url, int datasource_type
470
471
if(datasource_type == DATASOURCE_GOOGLE_JSONP) {
472
if(timestamp_in_data > last_timestamp_in_data)
478
- w->data->bytes += snprintf(&w->data->buffer[w->data->bytes], w->data->size - w->data->bytes, "});");
473
+ web_buffer_strcat(w->data, "});");
474
475
else {
476
// the client already has the latest data
482
- w->data->bytes = snprintf(w->data->buffer, w->data->size,
477
+ web_buffer_snprintf(w->data, 65536,
478
"%s({version:'%s',reqId:'%s',status:'error',errors:[{reason:'not_modified',message:'Data not modified'}]});",
479
google_responseHandler, google_version, google_reqId);
480
}
@@ -549,7 +544,7 @@ void web_client_process(struct web_client *w) {
544
global_statistics_unlock();
545
546
gettimeofday(&w->tv_in, NULL);
552
- debug(D_WEB_DATA, "%llu: Processing data buffer of %d bytes: '%s'.", w->id, w->data->bytes, w->data->buffer);
547
+ debug(D_WEB_DATA, "%llu: Processing data buffer of %d bytes: '%s'.", w->id, w->data->len, w->data->buffer);
548
549
// check if the client requested keep-alive HTTP
550
if(strcasestr(w->data->buffer, "Connection: keep-alive")) w->keepalive = 1;
@@ -614,19 +609,19 @@ void web_client_process(struct web_client *w) {
609
if(!st) {
610
// we don't have it
611
// try to send a file with that name
617
- w->data->bytes = 0;
612
+ web_buffer_flush(w->data);
613
code = mysendfile(w, tok);
614
}
615
else {
616
code = 200;
617
debug(D_WEB_CLIENT_ACCESS, "%llu: Sending %s.json of RRD_STATS...", w->id, st->name);
618
w->data->contenttype = CT_APPLICATION_JSON;
624
- w->data->bytes = 0;
619
+ web_buffer_flush(w->data);
620
rrd_stats_graph_json(st, url, w->data);
621
}
622
}
623
else if(strcmp(tok, "debug") == 0) {
629
- w->data->bytes = 0;
624
+ web_buffer_flush(w->data);
625
626
// get the name of the data to show
627
tok = mystrsep(&url, "/?&");
@@ -637,14 +632,14 @@ void web_client_process(struct web_client *w) {
632
if(!st) st = rrdset_find(tok);
633
if(!st) {
634
code = 404;
640
- web_buffer_printf(w->data, "Chart %s is not found.\r\n", tok);
635
+ web_buffer_snprintf(w->data, 1024, "Chart %s is not found.\r\n", tok);
636
debug(D_WEB_CLIENT_ACCESS, "%llu: %s is not found.", w->id, tok);
637
}
638
else {
639
code = 200;
640
debug_flags |= D_RRD_STATS;
641
st->debug = st->debug?0:1;
647
- web_buffer_printf(w->data, "Chart %s has now debug %s.\r\n", tok, st->debug?"enabled":"disabled");
642
+ web_buffer_snprintf(w->data, 1024, "Chart %s has now debug %s.\r\n", tok, st->debug?"enabled":"disabled");
643
debug(D_WEB_CLIENT_ACCESS, "%llu: debug for %s is %s.", w->id, tok, st->debug?"enabled":"disabled");
644
}
645
}
@@ -654,9 +649,7 @@ void web_client_process(struct web_client *w) {
649
debug(D_WEB_CLIENT_ACCESS, "%llu: Mirroring...", w->id);
650
651
// replace the zero bytes with spaces
657
- int i;
658
- for(i = 0; i < w->data->size; i++)
659
- if(w->data->buffer[i] == '\0') w->data->buffer[i] = ' ';
652
+ web_buffer_char_replace(w->data, '\0', ' ');
653
654
// just leave the buffer as is
655
// it will be copied back to the client
@@ -666,18 +659,18 @@ void web_client_process(struct web_client *w) {
659
660
debug(D_WEB_CLIENT_ACCESS, "%llu: Sending list of RRD_STATS...", w->id);
661
669
- w->data->bytes = 0;
662
+ web_buffer_flush(w->data);
663
RRDSET *st = rrdset_root;
664
665
for ( ; st ; st = st->next )
673
- web_buffer_printf(w->data, "%s\n", st->name);
666
+ web_buffer_snprintf(w->data, 1024, "%s\n", st->name);
667
}
668
else if(strcmp(tok, "all.json") == 0) {
669
code = 200;
670
debug(D_WEB_CLIENT_ACCESS, "%llu: Sending JSON list of all monitors of RRD_STATS...", w->id);
671
672
w->data->contenttype = CT_APPLICATION_JSON;
680
- w->data->bytes = 0;
673
+ web_buffer_flush(w->data);
674
rrd_stats_all_json(w->data);
675
}
676
else if(strcmp(tok, "netdata.conf") == 0) {
@@ -685,7 +678,7 @@ void web_client_process(struct web_client *w) {
678
debug(D_WEB_CLIENT_ACCESS, "%llu: Sending netdata.conf ...", w->id);
679
680
w->data->contenttype = CT_TEXT_PLAIN;
688
- w->data->bytes = 0;
681
+ web_buffer_flush(w->data);
682
generate_config(w->data, 0);
683
}
684
else if(strcmp(tok, WEB_PATH_FILE) == 0) { // "file"
@@ -693,17 +686,16 @@ void web_client_process(struct web_client *w) {
686
if(tok && *tok) code = mysendfile(w, tok);
687
else {
688
code = 400;
696
- w->data->bytes = 0;
697
- strcpy(w->data->buffer, "You have to give a filename to get.\r\n");
698
- w->data->bytes = strlen(w->data->buffer);
689
+ web_buffer_flush(w->data);
690
+ web_buffer_strcat(w->data, "You have to give a filename to get.\r\n");
691
}
692
}
693
else if(!tok[0]) {
702
- w->data->bytes = 0;
694
+ web_buffer_flush(w->data);
695
code = mysendfile(w, "index.html");
696
}
697
else {
706
- w->data->bytes = 0;
698
+ web_buffer_flush(w->data);
699
code = mysendfile(w, tok);
700
}
701
@@ -714,23 +706,21 @@ void web_client_process(struct web_client *w) {
706
if(buf) debug(D_WEB_CLIENT_ACCESS, "%llu: Cannot understand '%s'.", w->id, buf);
707
708
code = 500;
717
- w->data->bytes = 0;
718
- strcpy(w->data->buffer, "I don't understand you...\r\n");
719
- w->data->bytes = strlen(w->data->buffer);
709
+ web_buffer_flush(w->data);
710
+ web_buffer_strcat(w->data, "I don't understand you...\r\n");
711
}
712
713
// free url_decode() buffer
714
if(pointer_to_free) free(pointer_to_free);
715
}
725
- else if(w->data->bytes > 8192) {
716
+ else if(w->data->len > 8192) {
717
strcpy(w->last_url, "too big request");
718
719
debug(D_WEB_CLIENT_ACCESS, "%llu: Received request is too big.", w->id);
720
721
code = 400;
731
- w->data->bytes = 0;
732
- strcpy(w->data->buffer, "Received request is too big.\r\n");
733
- w->data->bytes = strlen(w->data->buffer);
722
+ web_buffer_flush(w->data);
723
+ web_buffer_strcat(w->data, "Received request is too big.\r\n");
724
}
725
else {
726
// wait for more data
@@ -738,8 +728,8 @@ void web_client_process(struct web_client *w) {
728
return;
729
}
730
741
- if(w->data->bytes > w->data->size) {
742
- error("%llu: memory overflow encountered (size is %ld, written %ld).", w->data->size, w->data->bytes);
731
+ if(w->data->len > w->data->size) {
732
+ error("%llu: memory overflow encountered (size is %ld, written %ld).", w->data->size, w->data->len);
733
}
734
735
gettimeofday(&w->tv_ready, NULL);
@@ -875,10 +865,10 @@ void web_client_process(struct web_client *w) {
865
}
866
867
// if we know the content length, put it
878
- if(!w->zoutput && (w->data->bytes || w->data->rbytes))
868
+ if(!w->zoutput && (w->data->len || w->data->rlen))
869
headerlen += snprintf(&w->response_header[headerlen], MAX_HTTP_HEADER_SIZE - headerlen,
870
"Content-Length: %ld\r\n"
881
- , w->data->bytes?w->data->bytes:w->data->rbytes
871
+ , w->data->len?w->data->len:w->data->rlen
872
);
873
else if(!w->zoutput)
874
w->keepalive = 0; // content-length is required for keep-alive
@@ -913,18 +903,18 @@ void web_client_process(struct web_client *w) {
903
if(setsockopt(w->ofd, IPPROTO_TCP, TCP_NODELAY, (char *) &flag, sizeof(int)) != 0) error("%llu: failed to enable TCP_NODELAY on socket.", w->id);
904
905
// enable sending immediately if we have data
916
- if(w->data->bytes) w->wait_send = 1;
906
+ if(w->data->len) w->wait_send = 1;
907
else w->wait_send = 0;
908
909
// pretty logging
910
switch(w->mode) {
911
case WEB_CLIENT_MODE_NORMAL:
922
- debug(D_WEB_CLIENT, "%llu: Done preparing the response. Sending data (%d bytes) to client.", w->id, w->data->bytes);
912
+ debug(D_WEB_CLIENT, "%llu: Done preparing the response. Sending data (%d bytes) to client.", w->id, w->data->len);
913
break;
914
915
case WEB_CLIENT_MODE_FILECOPY:
926
- if(w->data->rbytes) {
927
- debug(D_WEB_CLIENT, "%llu: Done preparing the response. Will be sending data file of %d bytes to client.", w->id, w->data->rbytes);
916
+ if(w->data->rlen) {
917
+ debug(D_WEB_CLIENT, "%llu: Done preparing the response. Will be sending data file of %d bytes to client.", w->id, w->data->rlen);
918
w->wait_receive = 1;
919
920
/*
@@ -991,14 +981,14 @@ long web_client_send_chunk_finalize(struct web_client *w)
981
#ifdef NETDATA_WITH_ZLIB
982
long web_client_send_deflate(struct web_client *w)
983
{
994
- long bytes = 0, t = 0;
984
+ long len = 0, t = 0;
985
986
// when using compression,
987
// w->data->sent is the amount of bytes passed through compression
988
989
// debug(D_DEFLATE, "%llu: TEST w->data->bytes = %d, w->data->sent = %d, w->zhave = %d, w->zsent = %d, w->zstream.avail_in = %d, w->zstream.avail_out = %d, w->zstream.total_in = %d, w->zstream.total_out = %d.", w->id, w->data->bytes, w->data->sent, w->zhave, w->zsent, w->zstream.avail_in, w->zstream.avail_out, w->zstream.total_in, w->zstream.total_out);
990
1001
- if(w->data->bytes - w->data->sent == 0 && w->zstream.avail_in == 0 && w->zhave == w->zsent && w->zstream.avail_out != 0) {
991
+ if(w->data->len - w->data->sent == 0 && w->zstream.avail_in == 0 && w->zhave == w->zsent && w->zstream.avail_out != 0) {
992
// there is nothing to send
993
994
debug(D_WEB_CLIENT, "%llu: Out of output data.", w->id);
@@ -1011,7 +1001,7 @@ long web_client_send_deflate(struct web_client *w)
1001
// A. we have done everything
1002
// B. we temporarily have nothing to send, waiting for the buffer to be filled by ifd
1003
1014
- if(w->mode == WEB_CLIENT_MODE_FILECOPY && w->wait_receive && w->ifd != w->ofd && w->data->rbytes && w->data->rbytes > w->data->bytes) {
1004
+ if(w->mode == WEB_CLIENT_MODE_FILECOPY && w->wait_receive && w->ifd != w->ofd && w->data->rlen && w->data->rlen > w->data->len) {
1005
// we have to wait, more data will come
1006
debug(D_WEB_CLIENT, "%llu: Waiting for more data to become available.", w->id);
1007
w->wait_send = 0;
@@ -1036,12 +1026,12 @@ long web_client_send_deflate(struct web_client *w)
1026
// close the previous open chunk
1027
if(w->data->sent != 0) t += web_client_send_chunk_close(w);
1028
1039
- debug(D_DEFLATE, "%llu: Compressing %d bytes starting from %d.", w->id, (w->data->bytes - w->data->sent), w->data->sent);
1029
+ debug(D_DEFLATE, "%llu: Compressing %d bytes starting from %d.", w->id, (w->data->len - w->data->sent), w->data->sent);
1030
1031
// give the compressor all the data not passed through the compressor yet
1042
- if(w->data->bytes > w->data->sent) {
1032
+ if(w->data->len > w->data->sent) {
1033
w->zstream.next_in = (Bytef *)&w->data->buffer[w->data->sent];
1044
- w->zstream.avail_in = (w->data->bytes - w->data->sent);
1034
+ w->zstream.avail_in = (w->data->len - w->data->sent);
1035
}
1036
1037
// reset the compressor output buffer
@@ -1051,7 +1041,7 @@ long web_client_send_deflate(struct web_client *w)
1041
// ask for FINISH if we have all the input
1042
int flush = Z_SYNC_FLUSH;
1043
if(w->mode == WEB_CLIENT_MODE_NORMAL
1054
- || (w->mode == WEB_CLIENT_MODE_FILECOPY && w->data->bytes == w->data->rbytes)) {
1044
+ || (w->mode == WEB_CLIENT_MODE_FILECOPY && w->data->len == w->data->rlen)) {
1045
flush = Z_FINISH;
1046
debug(D_DEFLATE, "%llu: Requesting Z_FINISH.", w->id);
1047
}
@@ -1070,7 +1060,7 @@ long web_client_send_deflate(struct web_client *w)
1060
w->zsent = 0;
1061
1062
// keep track of the bytes passed through the compressor
1073
- w->data->sent = w->data->bytes;
1063
+ w->data->sent = w->data->len;
1064
1065
debug(D_DEFLATE, "%llu: Compression produced %d bytes.", w->id, w->zhave);
1066
@@ -1078,16 +1068,16 @@ long web_client_send_deflate(struct web_client *w)
1068
t += web_client_send_chunk_header(w, w->zhave);
1069
}
1070
1081
- bytes = send(w->ofd, &w->zbuffer[w->zsent], w->zhave - w->zsent, MSG_DONTWAIT);
1082
- if(bytes > 0) {
1083
- w->zsent += bytes;
1084
- if(t > 0) bytes += t;
1085
- debug(D_WEB_CLIENT, "%llu: Sent %d bytes.", w->id, bytes);
1071
+ len = send(w->ofd, &w->zbuffer[w->zsent], w->zhave - w->zsent, MSG_DONTWAIT);
1072
+ if(len > 0) {
1073
+ w->zsent += len;
1074
+ if(t > 0) len += t;
1075
+ debug(D_WEB_CLIENT, "%llu: Sent %d bytes.", w->id, len);
1076
}
1087
- else if(bytes == 0) debug(D_WEB_CLIENT, "%llu: Did not send any bytes to the client.", w->id);
1077
+ else if(len == 0) debug(D_WEB_CLIENT, "%llu: Did not send any bytes to the client.", w->id);
1078
else debug(D_WEB_CLIENT, "%llu: Failed to send data to client. Reason: %s", w->id, strerror(errno));
1079
1090
- return(bytes);
1080
+ return(len);
1081
}
1082
#endif // NETDATA_WITH_ZLIB
1083
@@ -1099,7 +1089,7 @@ long web_client_send(struct web_client *w)
1089
1090
long bytes;
1091
1102
- if(unlikely(w->data->bytes - w->data->sent == 0)) {
1092
+ if(unlikely(w->data->len - w->data->sent == 0)) {
1093
// there is nothing to send
1094
1095
debug(D_WEB_CLIENT, "%llu: Out of output data.", w->id);
@@ -1108,7 +1098,7 @@ long web_client_send(struct web_client *w)
1098
// A. we have done everything
1099
// B. we temporarily have nothing to send, waiting for the buffer to be filled by ifd
1100
1111
- if(w->mode == WEB_CLIENT_MODE_FILECOPY && w->wait_receive && w->ifd != w->ofd && w->data->rbytes && w->data->rbytes > w->data->bytes) {
1101
+ if(w->mode == WEB_CLIENT_MODE_FILECOPY && w->wait_receive && w->ifd != w->ofd && w->data->rlen && w->data->rlen > w->data->len) {
1102
// we have to wait, more data will come
1103
debug(D_WEB_CLIENT, "%llu: Waiting for more data to become available.", w->id);
1104
w->wait_send = 0;
@@ -1126,7 +1116,7 @@ long web_client_send(struct web_client *w)
1116
return(0);
1117
}
1118
1129
- bytes = send(w->ofd, &w->data->buffer[w->data->sent], w->data->bytes - w->data->sent, MSG_DONTWAIT);
1119
+ bytes = send(w->ofd, &w->data->buffer[w->data->sent], w->data->len - w->data->sent, MSG_DONTWAIT);
1120
if(likely(bytes > 0)) {
1121
w->data->sent += bytes;
1122
debug(D_WEB_CLIENT, "%llu: Sent %d bytes.", w->id, bytes);
@@ -1140,27 +1130,27 @@ long web_client_send(struct web_client *w)
1130
long web_client_receive(struct web_client *w)
1131
{
1132
// do we have any space for more data?
1143
- web_buffer_increase(w->data, WEB_DATA_LENGTH_INCREASE_STEP);
1133
+ web_buffer_need_bytes(w->data, WEB_DATA_LENGTH_INCREASE_STEP);
1134
1145
- long left = w->data->size - w->data->bytes;
1135
+ long left = w->data->size - w->data->len;
1136
long bytes;
1137
1138
if(unlikely(w->mode == WEB_CLIENT_MODE_FILECOPY))
1149
- bytes = read(w->ifd, &w->data->buffer[w->data->bytes], (left-1));
1139
+ bytes = read(w->ifd, &w->data->buffer[w->data->len], (left-1));
1140
else
1151
- bytes = recv(w->ifd, &w->data->buffer[w->data->bytes], left-1, MSG_DONTWAIT);
1141
+ bytes = recv(w->ifd, &w->data->buffer[w->data->len], left-1, MSG_DONTWAIT);
1142
1143
if(likely(bytes > 0)) {
1154
- int old = w->data->bytes;
1155
- w->data->bytes += bytes;
1156
- w->data->buffer[w->data->bytes] = '\0';
1144
+ int old = w->data->len;
1145
+ w->data->len += bytes;
1146
+ w->data->buffer[w->data->len] = '\0';
1147
1148
debug(D_WEB_CLIENT, "%llu: Received %d bytes.", w->id, bytes);
1149
debug(D_WEB_DATA, "%llu: Received data: '%s'.", w->id, &w->data->buffer[old]);
1150
1151
if(w->mode == WEB_CLIENT_MODE_FILECOPY) {
1152
w->wait_send = 1;
1163
- if(w->data->rbytes && w->data->bytes >= w->data->rbytes) w->wait_receive = 0;
1153
+ if(w->data->rlen && w->data->len >= w->data->rlen) w->wait_receive = 0;
1154
}
1155
}
1156
else if(likely(bytes == 0)) {