@cryptotaxi247 / netdata-1 / commits / 5e3fc4fff

code cleanup and faster mime types assignement for static files

Costa Tsaousis (ktsaou) committed Dec 26, 2017 at 05:48 UTC 5e3fc4fff58f971800bb0611e668a158a167ebe8
4 files changed +141 -83
.gitignore
+6
@@ -97,6 +97,8 @@ cmake_install.cmake
97 contrib/debian/changelog
98 profile/benchmark-dictionary
99 profile/benchmark-registry
100 +profile/test-eval
101 +profile/benchmark-line-parsing
102
103 *.pyc
104 *.run
@@ -111,3 +113,7 @@ netdata.cppcheck
113 profile/statsd-stress
114 src/cgroup-network
115 vgcore.*
116 +
117 +src/cppcheck-build/
118 +makeself/debug/
119 +
src/rrd.h
+18 -18
@@ -105,13 +105,13 @@ typedef enum rrddim_flags {
105 } RRDDIM_FLAGS;
106
107 #ifdef HAVE_C___ATOMIC
108 -#define rrddim_flag_check(rd, flag) (__atomic_load_n(&((rd)->flags), __ATOMIC_SEQ_CST) & flag)
109 -#define rrddim_flag_set(rd, flag) __atomic_or_fetch(&((rd)->flags), flag, __ATOMIC_SEQ_CST)
110 -#define rrddim_flag_clear(rd, flag) __atomic_and_fetch(&((rd)->flags), ~flag, __ATOMIC_SEQ_CST)
108 +#define rrddim_flag_check(rd, flag) (__atomic_load_n(&((rd)->flags), __ATOMIC_SEQ_CST) & (flag))
109 +#define rrddim_flag_set(rd, flag) __atomic_or_fetch(&((rd)->flags), (flag), __ATOMIC_SEQ_CST)
110 +#define rrddim_flag_clear(rd, flag) __atomic_and_fetch(&((rd)->flags), ~(flag), __ATOMIC_SEQ_CST)
111 #else
112 -#define rrddim_flag_check(rd, flag) ((rd)->flags & flag)
113 -#define rrddim_flag_set(rd, flag) (rd)->flags |= flag
114 -#define rrddim_flag_clear(rd, flag) (rd)->flags &= ~flag
112 +#define rrddim_flag_check(rd, flag) ((rd)->flags & (flag))
113 +#define rrddim_flag_set(rd, flag) (rd)->flags |= (flag)
114 +#define rrddim_flag_clear(rd, flag) (rd)->flags &= ~(flag)
115 #endif
116
117
@@ -205,10 +205,10 @@ typedef struct rrddim RRDDIM;
205 // these loop macros make sure the linked list is accessed with the right lock
206
207 #define rrddim_foreach_read(rd, st) \
208 - for(rd = st->dimensions, rrdset_check_rdlock(st); rd ; rd = rd->next)
208 + for((rd) = (st)->dimensions, rrdset_check_rdlock(st); (rd) ; (rd) = (rd)->next)
209
210 #define rrddim_foreach_write(rd, st) \
211 - for(rd = st->dimensions, rrdset_check_wrlock(st); rd ; rd = rd->next)
211 + for((rd) = (st)->dimensions, rrdset_check_wrlock(st); (rd) ; (rd) = (rd)->next)
212
213
214 // ----------------------------------------------------------------------------
@@ -237,9 +237,9 @@ typedef enum rrdset_flags {
237 #define rrdset_flag_set(st, flag) __atomic_or_fetch(&((st)->flags), flag, __ATOMIC_SEQ_CST)
238 #define rrdset_flag_clear(st, flag) __atomic_and_fetch(&((st)->flags), ~flag, __ATOMIC_SEQ_CST)
239 #else
240 -#define rrdset_flag_check(st, flag) ((st)->flags & flag)
241 -#define rrdset_flag_set(st, flag) (st)->flags |= flag
242 -#define rrdset_flag_clear(st, flag) (st)->flags &= ~flag
240 +#define rrdset_flag_check(st, flag) ((st)->flags & (flag))
241 +#define rrdset_flag_set(st, flag) (st)->flags |= (flag)
242 +#define rrdset_flag_clear(st, flag) (st)->flags &= ~(flag)
243 #endif
244
245 struct rrdset {
@@ -360,10 +360,10 @@ typedef struct rrdset RRDSET;
360 // these loop macros make sure the linked list is accessed with the right lock
361
362 #define rrdset_foreach_read(st, host) \
363 - for(st = host->rrdset_root, rrdhost_check_rdlock(host); st ; st = st->next)
363 + for((st) = (host)->rrdset_root, rrdhost_check_rdlock(host); st ; (st) = (st)->next)
364
365 #define rrdset_foreach_write(st, host) \
366 - for(st = host->rrdset_root, rrdhost_check_wrlock(host); st ; st = st->next)
366 + for((st) = (host)->rrdset_root, rrdhost_check_wrlock(host); st ; (st) = (st)->next)
367
368
369 // ----------------------------------------------------------------------------
@@ -383,9 +383,9 @@ typedef enum rrdhost_flags {
383 #define rrdhost_flag_set(host, flag) __atomic_or_fetch(&((host)->flags), flag, __ATOMIC_SEQ_CST)
384 #define rrdhost_flag_clear(host, flag) __atomic_and_fetch(&((host)->flags), ~flag, __ATOMIC_SEQ_CST)
385 #else
386 -#define rrdhost_flag_check(host, flag) ((host)->flags & flag)
387 -#define rrdhost_flag_set(host, flag) (host)->flags |= flag
388 -#define rrdhost_flag_clear(host, flag) (host)->flags &= ~flag
386 +#define rrdhost_flag_check(host, flag) ((host)->flags & (flag))
387 +#define rrdhost_flag_set(host, flag) (host)->flags |= (flag)
388 +#define rrdhost_flag_clear(host, flag) (host)->flags &= ~(flag)
389 #endif
390
391 #ifdef NETDATA_INTERNAL_CHECKS
@@ -520,10 +520,10 @@ extern RRDHOST *localhost;
520 // these loop macros make sure the linked list is accessed with the right lock
521
522 #define rrdhost_foreach_read(var) \
523 - for(var = localhost, rrd_check_rdlock(); var ; var = var->next)
523 + for((var) = localhost, rrd_check_rdlock(); var ; (var) = (var)->next)
524
525 #define rrdhost_foreach_write(var) \
526 - for(var = localhost, rrd_check_wrlock(); var ; var = var->next)
526 + for((var) = localhost, rrd_check_wrlock(); var ; (var) = (var)->next)
527
528
529 // ----------------------------------------------------------------------------
src/rrdpush.c
+4 -3
@@ -140,19 +140,20 @@ static inline void rrdpush_send_chart_definition_nolock(RRDSET *st) {
140
141 // sends the current chart dimensions
142 static inline void rrdpush_send_chart_metrics_nolock(RRDSET *st) {
143 - buffer_sprintf(st->rrdhost->rrdpush_sender_buffer, "BEGIN \"%s\" %llu\n", st->id, (st->upstream_resync_time > st->last_collected_time.tv_sec)?st->usec_since_last_update:0);
143 + RRDHOST *host = st->rrdhost;
144 + buffer_sprintf(host->rrdpush_sender_buffer, "BEGIN \"%s\" %llu\n", st->id, (st->upstream_resync_time > st->last_collected_time.tv_sec)?st->usec_since_last_update:0);
145
146 RRDDIM *rd;
147 rrddim_foreach_read(rd, st) {
148 if(rd->updated && rd->exposed)
148 - buffer_sprintf(st->rrdhost->rrdpush_sender_buffer
149 + buffer_sprintf(host->rrdpush_sender_buffer
150 , "SET \"%s\" = " COLLECTED_NUMBER_FORMAT "\n"
151 , rd->id
152 , rd->collected_value
153 );
154 }
155
155 - buffer_strcat(st->rrdhost->rrdpush_sender_buffer, "END\n");
156 + buffer_strcat(host->rrdpush_sender_buffer, "END\n");
157 }
158
159 static void rrdpush_sender_thread_spawn(RRDHOST *host);
src/web_client.c
+113 -62
@@ -344,6 +344,81 @@ gid_t web_files_gid(void) {
344 return(owner_gid);
345 }
346
347 +static struct mime_type {
348 + const char *extension;
349 + uint32_t hash;
350 + uint8_t contenttype;
351 +} mime_types[] = {
352 + { "html" , 0 , CT_TEXT_HTML}
353 + , {"js" , 0 , CT_APPLICATION_X_JAVASCRIPT}
354 + , {"css" , 0 , CT_TEXT_CSS}
355 + , {"xml" , 0 , CT_TEXT_XML}
356 + , {"xsl" , 0 , CT_TEXT_XSL}
357 + , {"txt" , 0 , CT_TEXT_PLAIN}
358 + , {"svg" , 0 , CT_IMAGE_SVG_XML}
359 + , {"ttf" , 0 , CT_APPLICATION_X_FONT_TRUETYPE}
360 + , {"otf" , 0 , CT_APPLICATION_X_FONT_OPENTYPE}
361 + , {"woff2", 0 , CT_APPLICATION_FONT_WOFF2}
362 + , {"woff" , 0 , CT_APPLICATION_FONT_WOFF}
363 + , {"eot" , 0 , CT_APPLICATION_VND_MS_FONTOBJ}
364 + , {"png" , 0 , CT_IMAGE_PNG}
365 + , {"jpg" , 0 , CT_IMAGE_JPG}
366 + , {"jpeg" , 0 , CT_IMAGE_JPG}
367 + , {"gif" , 0 , CT_IMAGE_GIF}
368 + , {"bmp" , 0 , CT_IMAGE_BMP}
369 + , {"ico" , 0 , CT_IMAGE_XICON}
370 + , {"icns" , 0 , CT_IMAGE_ICNS}
371 + , { NULL, 0, 0}
372 +};
373 +
374 +static inline uint8_t contenttype_for_filename(const char *filename) {
375 + // info("checking filename '%s'", filename);
376 +
377 + static int initialized = 0;
378 + int i;
379 +
380 + if(unlikely(!initialized)) {
381 + for (i = 0; mime_types[i].extension; i++)
382 + mime_types[i].hash = simple_hash(mime_types[i].extension);
383 +
384 + initialized = 1;
385 + }
386 +
387 + const char *s = filename, *last_dot = NULL;
388 +
389 + // find the last dot
390 + while(*s) {
391 + if(unlikely(*s == '.')) last_dot = s;
392 + s++;
393 + }
394 +
395 + if(unlikely(!last_dot || !*last_dot || !last_dot[1])) {
396 + // info("no extension for filename '%s'", filename);
397 + return CT_APPLICATION_OCTET_STREAM;
398 + }
399 + last_dot++;
400 +
401 + // info("extension for filename '%s' is '%s'", filename, last_dot);
402 +
403 + uint32_t hash = simple_hash(last_dot);
404 + for(i = 0; mime_types[i].extension ; i++) {
405 + if(unlikely(hash == mime_types[i].hash && !strcmp(last_dot, mime_types[i].extension))) {
406 + // info("matched extension for filename '%s': '%s'", filename, last_dot);
407 + return mime_types[i].contenttype;
408 + }
409 + }
410 +
411 + // info("not matched extension for filename '%s': '%s'", filename, last_dot);
412 + return CT_APPLICATION_OCTET_STREAM;
413 +}
414 +
415 +static inline int access_to_file_is_not_permitted(struct web_client *w, const char *filename) {
416 + w->response.data->contenttype = CT_TEXT_HTML;
417 + buffer_strcat(w->response.data, "Access to file is not permitted: ");
418 + buffer_strcat_htmlescape(w->response.data, filename);
419 + return 403;
420 +}
421 +
422 int mysendfile(struct web_client *w, char *filename) {
423 debug(D_WEB_CLIENT, "%llu: Looking for file '%s/%s'", w->id, netdata_configured_web_dir, filename);
424
@@ -357,6 +432,7 @@ int mysendfile(struct web_client *w, char *filename) {
432 if(strncmp(filename, WEB_PATH_FILE "/", strlen(WEB_PATH_FILE) + 1) == 0)
433 filename = &filename[strlen(WEB_PATH_FILE) + 1];
434
435 + // if the filename contains "strange" characters, refuse to serve it
436 char *s;
437 for(s = filename; *s ;s++) {
438 if( !isalnum(*s) && *s != '/' && *s != '.' && *s != '-' && *s != '_') {
@@ -377,49 +453,45 @@ int mysendfile(struct web_client *w, char *filename) {
453 return 400;
454 }
455
380 - // access the file
456 + // find the physical file on disk
457 char webfilename[FILENAME_MAX + 1];
458 snprintfz(webfilename, FILENAME_MAX, "%s/%s", netdata_configured_web_dir, filename);
459
384 - // check if the file exists
385 - struct stat stat;
386 - if(lstat(webfilename, &stat) != 0) {
387 - debug(D_WEB_CLIENT_ACCESS, "%llu: File '%s' is not found.", w->id, webfilename);
388 - w->response.data->contenttype = CT_TEXT_HTML;
389 - buffer_strcat(w->response.data, "File does not exist, or is not accessible: ");
390 - buffer_strcat_htmlescape(w->response.data, webfilename);
391 - return 404;
392 - }
460 + struct stat statbuf;
461 + int done = 0;
462 + while(!done) {
463 + // check if the file exists
464 + if (lstat(webfilename, &statbuf) != 0) {
465 + debug(D_WEB_CLIENT_ACCESS, "%llu: File '%s' is not found.", w->id, webfilename);
466 + w->response.data->contenttype = CT_TEXT_HTML;
467 + buffer_strcat(w->response.data, "File does not exist, or is not accessible: ");
468 + buffer_strcat_htmlescape(w->response.data, webfilename);
469 + return 404;
470 + }
471
394 - // check if the file is owned by expected user
395 - if(stat.st_uid != web_files_uid()) {
396 - error("%llu: File '%s' is owned by user %u (expected user %u). Access Denied.", w->id, webfilename, stat.st_uid, web_files_uid());
397 - w->response.data->contenttype = CT_TEXT_HTML;
398 - buffer_strcat(w->response.data, "Access to file is not permitted: ");
399 - buffer_strcat_htmlescape(w->response.data, webfilename);
400 - return 403;
401 - }
472 + if ((statbuf.st_mode & S_IFMT) == S_IFDIR) {
473 + snprintfz(webfilename, FILENAME_MAX, "%s/%s/index.html", netdata_configured_web_dir, filename);
474 + continue;
475 + }
476
403 - // check if the file is owned by expected group
404 - if(stat.st_gid != web_files_gid()) {
405 - error("%llu: File '%s' is owned by group %u (expected group %u). Access Denied.", w->id, webfilename, stat.st_gid, web_files_gid());
406 - w->response.data->contenttype = CT_TEXT_HTML;
407 - buffer_strcat(w->response.data, "Access to file is not permitted: ");
408 - buffer_strcat_htmlescape(w->response.data, webfilename);
409 - return 403;
410 - }
477 + if ((statbuf.st_mode & S_IFMT) != S_IFREG) {
478 + error("%llu: File '%s' is not a regular file. Access Denied.", w->id, webfilename);
479 + return access_to_file_is_not_permitted(w, webfilename);
480 + }
481
412 - if((stat.st_mode & S_IFMT) == S_IFDIR) {
413 - snprintfz(webfilename, FILENAME_MAX, "%s/index.html", filename);
414 - return mysendfile(w, webfilename);
415 - }
482 + // check if the file is owned by expected user
483 + if (statbuf.st_uid != web_files_uid()) {
484 + error("%llu: File '%s' is owned by user %u (expected user %u). Access Denied.", w->id, webfilename, statbuf.st_uid, web_files_uid());
485 + return access_to_file_is_not_permitted(w, webfilename);
486 + }
487
417 - if((stat.st_mode & S_IFMT) != S_IFREG) {
418 - error("%llu: File '%s' is not a regular file. Access Denied.", w->id, webfilename);
419 - w->response.data->contenttype = CT_TEXT_HTML;
420 - buffer_strcat(w->response.data, "Access to file is not permitted: ");
421 - buffer_strcat_htmlescape(w->response.data, webfilename);
422 - return 403;
488 + // check if the file is owned by expected group
489 + if (statbuf.st_gid != web_files_gid()) {
490 + error("%llu: File '%s' is owned by group %u (expected group %u). Access Denied.", w->id, webfilename, statbuf.st_gid, web_files_gid());
491 + return access_to_file_is_not_permitted(w, webfilename);
492 + }
493 +
494 + done = 1;
495 }
496
497 // open the file
@@ -446,39 +518,18 @@ int mysendfile(struct web_client *w, char *filename) {
518
519 sock_setnonblock(w->ifd);
520
449 - // pick a Content-Type for the file
450 - if(strstr(filename, ".html") != NULL) w->response.data->contenttype = CT_TEXT_HTML;
451 - else if(strstr(filename, ".js") != NULL) w->response.data->contenttype = CT_APPLICATION_X_JAVASCRIPT;
452 - else if(strstr(filename, ".css") != NULL) w->response.data->contenttype = CT_TEXT_CSS;
453 - else if(strstr(filename, ".xml") != NULL) w->response.data->contenttype = CT_TEXT_XML;
454 - else if(strstr(filename, ".xsl") != NULL) w->response.data->contenttype = CT_TEXT_XSL;
455 - else if(strstr(filename, ".txt") != NULL) w->response.data->contenttype = CT_TEXT_PLAIN;
456 - else if(strstr(filename, ".svg") != NULL) w->response.data->contenttype = CT_IMAGE_SVG_XML;
457 - else if(strstr(filename, ".ttf") != NULL) w->response.data->contenttype = CT_APPLICATION_X_FONT_TRUETYPE;
458 - else if(strstr(filename, ".otf") != NULL) w->response.data->contenttype = CT_APPLICATION_X_FONT_OPENTYPE;
459 - else if(strstr(filename, ".woff2")!= NULL) w->response.data->contenttype = CT_APPLICATION_FONT_WOFF2;
460 - else if(strstr(filename, ".woff") != NULL) w->response.data->contenttype = CT_APPLICATION_FONT_WOFF;
461 - else if(strstr(filename, ".eot") != NULL) w->response.data->contenttype = CT_APPLICATION_VND_MS_FONTOBJ;
462 - else if(strstr(filename, ".png") != NULL) w->response.data->contenttype = CT_IMAGE_PNG;
463 - else if(strstr(filename, ".jpg") != NULL) w->response.data->contenttype = CT_IMAGE_JPG;
464 - else if(strstr(filename, ".jpeg") != NULL) w->response.data->contenttype = CT_IMAGE_JPG;
465 - else if(strstr(filename, ".gif") != NULL) w->response.data->contenttype = CT_IMAGE_GIF;
466 - else if(strstr(filename, ".bmp") != NULL) w->response.data->contenttype = CT_IMAGE_BMP;
467 - else if(strstr(filename, ".ico") != NULL) w->response.data->contenttype = CT_IMAGE_XICON;
468 - else if(strstr(filename, ".icns") != NULL) w->response.data->contenttype = CT_IMAGE_ICNS;
469 - else w->response.data->contenttype = CT_APPLICATION_OCTET_STREAM;
470 -
471 - debug(D_WEB_CLIENT_ACCESS, "%llu: Sending file '%s' (%ld bytes, ifd %d, ofd %d).", w->id, webfilename, stat.st_size, w->ifd, w->ofd);
521 + w->response.data->contenttype = contenttype_for_filename(webfilename);
522 + debug(D_WEB_CLIENT_ACCESS, "%llu: Sending file '%s' (%ld bytes, ifd %d, ofd %d).", w->id, webfilename, statbuf.st_size, w->ifd, w->ofd);
523
524 w->mode = WEB_CLIENT_MODE_FILECOPY;
525 web_client_enable_wait_receive(w);
526 web_client_disable_wait_send(w);
527 buffer_flush(w->response.data);
477 - w->response.rlen = stat.st_size;
528 + w->response.rlen = (size_t)statbuf.st_size;
529 #ifdef __APPLE__
479 - w->response.data->date = stat.st_mtimespec.tv_sec;
530 + w->response.data->date = statbuf.st_mtimespec.tv_sec;
531 #else
481 - w->response.data->date = stat.st_mtim.tv_sec;
532 + w->response.data->date = statbuf.st_mtim.tv_sec;
533 #endif /* __APPLE__ */
534 buffer_cacheable(w->response.data);
535