26
*
27
*/
28
29
-#define STREAMING_PROTOCOL_VERSION "1.1"
30
-#define START_STREAMING_PROMPT "Hit me baby, push them over..."
31
-#define START_STREAMING_PROMPT_V2 "Hit me baby, push them over and bring the host labels..."
32
-#define START_STREAMING_PROMPT_VN "Hit me baby, push them over with the version="
33
-
34
-typedef enum {
35
- RRDPUSH_MULTIPLE_CONNECTIONS_ALLOW,
36
- RRDPUSH_MULTIPLE_CONNECTIONS_DENY_NEW
37
-} RRDPUSH_MULTIPLE_CONNECTIONS_STRATEGY;
38
-
39
-typedef struct {
40
- char *os_name;
41
- char *os_id;
42
- char *os_version;
43
- char *kernel_name;
44
- char *kernel_version;
45
-} stream_encoded_t;
46
-
47
-static struct config stream_config = {
29
+struct config stream_config = {
30
.first_section = NULL,
31
.last_section = NULL,
32
.mutex = NETDATA_MUTEX_INITIALIZER,
107
return default_rrdpush_enabled;
108
}
109
128
-#define CONNECTED_TO_SIZE 100
129
-
110
// data collection happens from multiple threads
111
// each of these threads calls rrdset_done()
112
// which in turn calls rrdset_done_push()
121
// this is for the first iterations of each chart
122
unsigned int remote_clock_resync_iterations = 60;
123
144
-#define rrdpush_buffer_lock(host) netdata_mutex_lock(&((host)->rrdpush_sender_buffer_mutex))
145
-#define rrdpush_buffer_unlock(host) netdata_mutex_unlock(&((host)->rrdpush_sender_buffer_mutex))
124
125
static inline int should_send_chart_matching(RRDSET *st) {
126
if(unlikely(!rrdset_flag_check(st, RRDSET_FLAG_ENABLED))) {
183
return 0;
184
}
185
208
-// sends the current chart definition
186
+// Send the current chart definition.
187
+// Assumes that collector thread has already called sender_start for mutex / buffer state.
188
static inline void rrdpush_send_chart_definition_nolock(RRDSET *st) {
189
RRDHOST *host = st->rrdhost;
190
203
}
204
}
205
227
- // info("CHART '%s' '%s'", st->id, name);
228
-
206
// send the chart
207
buffer_sprintf(
231
- host->rrdpush_sender_buffer
208
+ host->sender->build
209
, "CHART \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" %ld %d \"%s %s %s %s\" \"%s\" \"%s\"\n"
210
, st->id
211
, name
228
RRDDIM *rd;
229
rrddim_foreach_read(rd, st) {
230
buffer_sprintf(
254
- host->rrdpush_sender_buffer
231
+ host->sender->build
232
, "DIMENSION \"%s\" \"%s\" \"%s\" " COLLECTED_NUMBER_FORMAT " " COLLECTED_NUMBER_FORMAT " \"%s %s %s\"\n"
233
, rd->id
234
, rd->name
249
calculated_number *value = (calculated_number *) rs->value;
250
251
buffer_sprintf(
275
- host->rrdpush_sender_buffer
252
+ host->sender->build
253
, "VARIABLE CHART %s = " CALCULATED_NUMBER_FORMAT "\n"
254
, rs->variable
255
, *value
261
}
262
263
// sends the current chart dimensions
287
-static inline void rrdpush_send_chart_metrics_nolock(RRDSET *st) {
264
+static inline void rrdpush_send_chart_metrics_nolock(RRDSET *st, struct sender_state *s) {
265
RRDHOST *host = st->rrdhost;
289
- buffer_sprintf(host->rrdpush_sender_buffer, "BEGIN \"%s\" %llu\n", st->id, (st->last_collected_time.tv_sec > st->upstream_resync_time)?st->usec_since_last_update:0);
266
+ buffer_sprintf(host->sender->build, "BEGIN \"%s\" %llu", st->id, (st->last_collected_time.tv_sec > st->upstream_resync_time)?st->usec_since_last_update:0);
267
+ if (s->version >= VERSION_GAP_FILLING)
268
+ buffer_sprintf(host->sender->build, " %ld\n", st->last_collected_time.tv_sec);
269
+ else
270
+ buffer_strcat(host->sender->build, "\n");
271
272
RRDDIM *rd;
273
rrddim_foreach_read(rd, st) {
274
if(rd->updated && rd->exposed)
294
- buffer_sprintf(host->rrdpush_sender_buffer
275
+ buffer_sprintf(host->sender->build
276
, "SET \"%s\" = " COLLECTED_NUMBER_FORMAT "\n"
277
, rd->id
278
, rd->collected_value
279
);
280
}
300
-
301
- buffer_strcat(host->rrdpush_sender_buffer, "END\n");
281
+ buffer_strcat(host->sender->build, "END\n");
282
}
283
284
static void rrdpush_sender_thread_spawn(RRDHOST *host);
285
286
+// Called from the internal collectors to mark a chart obsolete.
287
void rrdset_push_chart_definition_now(RRDSET *st) {
288
RRDHOST *host = st->rrdhost;
289
291
return;
292
293
rrdset_rdlock(st);
313
- rrdpush_buffer_lock(host);
294
+ sender_start(host->sender);
295
rrdpush_send_chart_definition_nolock(st);
315
- rrdpush_buffer_unlock(host);
296
+ sender_commit(host->sender);
297
rrdset_unlock(st);
298
}
299
303
304
RRDHOST *host = st->rrdhost;
305
325
- rrdpush_buffer_lock(host);
326
-
306
if(unlikely(host->rrdpush_send_enabled && !host->rrdpush_sender_spawn))
307
rrdpush_sender_thread_spawn(host);
308
330
- if(unlikely(!host->rrdpush_sender_buffer || !host->rrdpush_sender_connected)) {
309
+ // Handle non-connected case
310
+ if(unlikely(!host->rrdpush_sender_connected)) {
311
if(unlikely(!host->rrdpush_sender_error_shown))
312
error("STREAM %s [send]: not ready - discarding collected metrics.", host->hostname);
333
-
313
host->rrdpush_sender_error_shown = 1;
335
-
336
- rrdpush_buffer_unlock(host);
314
return;
315
}
316
else if(unlikely(host->rrdpush_sender_error_shown)) {
318
host->rrdpush_sender_error_shown = 0;
319
}
320
321
+ sender_start(host->sender);
322
+
323
if(need_to_send_chart_definition(st))
324
rrdpush_send_chart_definition_nolock(st);
325
347
- rrdpush_send_chart_metrics_nolock(st);
326
+ rrdpush_send_chart_metrics_nolock(st, host->sender);
327
328
// signal the sender there are more data
329
if(host->rrdpush_sender_pipe[PIPE_WRITE] != -1 && write(host->rrdpush_sender_pipe[PIPE_WRITE], " ", 1) == -1)
330
error("STREAM %s [send]: cannot write to internal pipe", host->hostname);
331
353
- rrdpush_buffer_unlock(host);
332
+ sender_commit(host->sender);
333
}
334
335
// labels
337
if (!host->labels || !(host->labels_flag & LABEL_FLAG_UPDATE_STREAM) || (host->labels_flag & LABEL_FLAG_STOP_STREAM))
338
return;
339
361
- rrdpush_buffer_lock(host);
340
+ sender_start(host->sender);
341
rrdhost_rdlock(host);
342
netdata_rwlock_rdlock(&host->labels_rwlock);
343
344
struct label *labels = host->labels;
345
while(labels) {
367
- buffer_sprintf(host->rrdpush_sender_buffer
346
+ buffer_sprintf(host->sender->build
347
, "LABEL \"%s\" = %d %s\n"
348
, labels->key
349
, (int)labels->label_source
352
labels = labels->next;
353
}
354
376
- buffer_sprintf(host->rrdpush_sender_buffer
355
+ buffer_sprintf(host->sender->build
356
, "OVERWRITE %s\n", "labels");
357
358
netdata_rwlock_unlock(&host->labels_rwlock);
359
rrdhost_unlock(host);
360
+ sender_commit(host->sender);
361
362
if(host->rrdpush_sender_pipe[PIPE_WRITE] != -1 && write(host->rrdpush_sender_pipe[PIPE_WRITE], " ", 1) == -1)
363
error("STREAM %s [send]: cannot write to internal pipe", host->hostname);
364
385
- rrdpush_buffer_unlock(host);
365
host->labels_flag &= ~LABEL_FLAG_UPDATE_STREAM;
366
}
367
// ----------------------------------------------------------------------------
368
// rrdpush sender thread
369
391
-static inline void rrdpush_sender_add_host_variable_to_buffer_nolock(RRDHOST *host, RRDVAR *rv) {
392
- calculated_number *value = (calculated_number *)rv->value;
393
-
394
- buffer_sprintf(
395
- host->rrdpush_sender_buffer
396
- , "VARIABLE HOST %s = " CALCULATED_NUMBER_FORMAT "\n"
397
- , rv->name
398
- , *value
399
- );
400
-
401
- debug(D_STREAM, "RRDVAR pushed HOST VARIABLE %s = " CALCULATED_NUMBER_FORMAT, rv->name, *value);
402
-}
403
-
404
-void rrdpush_sender_send_this_host_variable_now(RRDHOST *host, RRDVAR *rv) {
405
- if(host->rrdpush_send_enabled && host->rrdpush_sender_spawn && host->rrdpush_sender_connected) {
406
- rrdpush_buffer_lock(host);
407
- rrdpush_sender_add_host_variable_to_buffer_nolock(host, rv);
408
- rrdpush_buffer_unlock(host);
409
- }
410
-}
411
-
412
-static int rrdpush_sender_thread_custom_host_variables_callback(void *rrdvar_ptr, void *host_ptr) {
413
- RRDVAR *rv = (RRDVAR *)rrdvar_ptr;
414
- RRDHOST *host = (RRDHOST *)host_ptr;
415
-
416
- if(unlikely(rv->options & RRDVAR_OPTION_CUSTOM_HOST_VAR && rv->type == RRDVAR_TYPE_CALCULATED)) {
417
- rrdpush_sender_add_host_variable_to_buffer_nolock(host, rv);
418
-
419
- // return 1, so that the traversal will return the number of variables sent
420
- return 1;
421
- }
422
-
423
- // returning a negative number will break the traversal
424
- return 0;
425
-}
426
-
427
-static void rrdpush_sender_thread_send_custom_host_variables(RRDHOST *host) {
428
- int ret = rrdvar_callback_for_all_host_variables(host, rrdpush_sender_thread_custom_host_variables_callback, host);
429
- (void)ret;
430
-
431
- debug(D_STREAM, "RRDVAR sent %d VARIABLES", ret);
432
-}
433
-
434
-// resets all the chart, so that their definitions
435
-// will be resent to the central netdata
436
-static void rrdpush_sender_thread_reset_all_charts(RRDHOST *host) {
437
- rrdhost_rdlock(host);
438
-
439
- RRDSET *st;
440
- rrdset_foreach_read(st, host) {
441
- rrdset_flag_clear(st, RRDSET_FLAG_UPSTREAM_EXPOSED);
442
-
443
- st->upstream_resync_time = 0;
444
-
445
- rrdset_rdlock(st);
446
-
447
- RRDDIM *rd;
448
- rrddim_foreach_read(rd, st)
449
- rd->exposed = 0;
450
-
451
- rrdset_unlock(st);
452
- }
453
-
454
- rrdhost_unlock(host);
455
-}
456
-
457
-static inline void rrdpush_sender_thread_data_flush(RRDHOST *host) {
458
- rrdpush_buffer_lock(host);
459
-
460
- if(buffer_strlen(host->rrdpush_sender_buffer))
461
- error("STREAM %s [send]: discarding %zu bytes of metrics already in the buffer.", host->hostname, buffer_strlen(host->rrdpush_sender_buffer));
462
-
463
- buffer_flush(host->rrdpush_sender_buffer);
464
-
465
- rrdpush_sender_thread_reset_all_charts(host);
466
- rrdpush_sender_thread_send_custom_host_variables(host);
467
-
468
- rrdpush_buffer_unlock(host);
469
-}
470
-
370
+// Either the receiver lost the connection or the host is being destroyed.
371
+// Don't lock the sender buffer - doesn't affect consistency in either case.
372
+// TODO-GAPS During the host destruction sequence we should make sure the disconnect happens early enough to lock
373
+// out collectors hitting the sender. Locking the mutex means there may be waiting threads when we free.
374
void rrdpush_sender_thread_stop(RRDHOST *host) {
472
- rrdpush_buffer_lock(host);
375
rrdhost_wrlock(host);
376
377
netdata_thread_t thr = 0;
391
}
392
393
rrdhost_unlock(host);
492
- rrdpush_buffer_unlock(host);
394
395
if(thr != 0) {
396
info("STREAM %s [send]: waiting for the sending thread to stop...", host->hostname);
400
}
401
}
402
502
-static inline void rrdpush_sender_thread_close_socket(RRDHOST *host) {
503
- host->rrdpush_sender_connected = 0;
504
-
505
- if(host->rrdpush_sender_socket != -1) {
506
- close(host->rrdpush_sender_socket);
507
- host->rrdpush_sender_socket = -1;
508
- }
509
-}
510
-
511
-static inline void rrdpush_set_flags_to_newest_stream(RRDHOST *host) {
512
- host->labels_flag |= LABEL_FLAG_UPDATE_STREAM;
513
- host->labels_flag &= ~LABEL_FLAG_STOP_STREAM;
514
-}
515
-
516
-void rrdpush_encode_variable(stream_encoded_t *se, RRDHOST *host)
517
-{
518
- se->os_name = (host->system_info->host_os_name)?url_encode(host->system_info->host_os_name):"";
519
- se->os_id = (host->system_info->host_os_id)?url_encode(host->system_info->host_os_id):"";
520
- se->os_version = (host->system_info->host_os_version)?url_encode(host->system_info->host_os_version):"";
521
- se->kernel_name = (host->system_info->kernel_name)?url_encode(host->system_info->kernel_name):"";
522
- se->kernel_version = (host->system_info->kernel_version)?url_encode(host->system_info->kernel_version):"";
523
-}
524
-
525
-void rrdpush_clean_encoded(stream_encoded_t *se)
526
-{
527
- if (se->os_name)
528
- freez(se->os_name);
529
-
530
- if (se->os_id)
531
- freez(se->os_id);
532
-
533
- if (se->os_version)
534
- freez(se->os_version);
535
-
536
- if (se->kernel_name)
537
- freez(se->kernel_name);
538
-
539
- if (se->kernel_version)
540
- freez(se->kernel_version);
541
-}
542
-
543
-//called from client side
544
-static int rrdpush_sender_thread_connect_to_master(RRDHOST *host, int default_port, int timeout, size_t *reconnects_counter, char *connected_to, size_t connected_to_size) {
545
- struct timeval tv = {
546
- .tv_sec = timeout,
547
- .tv_usec = 0
548
- };
549
-
550
- // make sure the socket is closed
551
- rrdpush_sender_thread_close_socket(host);
552
-
553
- debug(D_STREAM, "STREAM: Attempting to connect...");
554
- info("STREAM %s [send to %s]: connecting...", host->hostname, host->rrdpush_send_destination);
555
-
556
- host->rrdpush_sender_socket = connect_to_one_of(
557
- host->rrdpush_send_destination
558
- , default_port
559
- , &tv
560
- , reconnects_counter
561
- , connected_to
562
- , connected_to_size
563
- );
564
-
565
- if(unlikely(host->rrdpush_sender_socket == -1)) {
566
- error("STREAM %s [send to %s]: failed to connect", host->hostname, host->rrdpush_send_destination);
567
- return 0;
568
- }
569
-
570
- info("STREAM %s [send to %s]: initializing communication...", host->hostname, connected_to);
571
-
572
-#ifdef ENABLE_HTTPS
573
- if( netdata_client_ctx ){
574
- host->ssl.flags = NETDATA_SSL_START;
575
- if (!host->ssl.conn){
576
- host->ssl.conn = SSL_new(netdata_client_ctx);
577
- if(!host->ssl.conn){
578
- error("Failed to allocate SSL structure.");
579
- host->ssl.flags = NETDATA_SSL_NO_HANDSHAKE;
580
- }
581
- }
582
- else{
583
- SSL_clear(host->ssl.conn);
584
- }
585
-
586
- if (host->ssl.conn)
587
- {
588
- if (SSL_set_fd(host->ssl.conn, host->rrdpush_sender_socket) != 1) {
589
- error("Failed to set the socket to the SSL on socket fd %d.", host->rrdpush_sender_socket);
590
- host->ssl.flags = NETDATA_SSL_NO_HANDSHAKE;
591
- } else{
592
- host->ssl.flags = NETDATA_SSL_HANDSHAKE_COMPLETE;
593
- }
594
- }
595
- }
596
- else {
597
- host->ssl.flags = NETDATA_SSL_NO_HANDSHAKE;
598
- }
599
-#endif
600
-
601
- /* TODO: During the implementation of #7265 switch the set of variables to HOST_* and CONTAINER_* if the
602
- version negotiation resulted in a high enough version.
603
- */
604
- stream_encoded_t se;
605
- rrdpush_encode_variable(&se, host);
606
-
607
- #define HTTP_HEADER_SIZE 8192
608
- char http[HTTP_HEADER_SIZE + 1];
609
- int eol = snprintfz(http, HTTP_HEADER_SIZE,
610
- "STREAM key=%s&hostname=%s®istry_hostname=%s&machine_guid=%s&update_every=%d&os=%s&timezone=%s&tags=%s&ver=%u"
611
- "&NETDATA_SYSTEM_OS_NAME=%s"
612
- "&NETDATA_SYSTEM_OS_ID=%s"
613
- "&NETDATA_SYSTEM_OS_ID_LIKE=%s"
614
- "&NETDATA_SYSTEM_OS_VERSION=%s"
615
- "&NETDATA_SYSTEM_OS_VERSION_ID=%s"
616
- "&NETDATA_SYSTEM_OS_DETECTION=%s"
617
- "&NETDATA_SYSTEM_KERNEL_NAME=%s"
618
- "&NETDATA_SYSTEM_KERNEL_VERSION=%s"
619
- "&NETDATA_SYSTEM_ARCHITECTURE=%s"
620
- "&NETDATA_SYSTEM_VIRTUALIZATION=%s"
621
- "&NETDATA_SYSTEM_VIRT_DETECTION=%s"
622
- "&NETDATA_SYSTEM_CONTAINER=%s"
623
- "&NETDATA_SYSTEM_CONTAINER_DETECTION=%s"
624
- "&NETDATA_CONTAINER_OS_NAME=%s"
625
- "&NETDATA_CONTAINER_OS_ID=%s"
626
- "&NETDATA_CONTAINER_OS_ID_LIKE=%s"
627
- "&NETDATA_CONTAINER_OS_VERSION=%s"
628
- "&NETDATA_CONTAINER_OS_VERSION_ID=%s"
629
- "&NETDATA_CONTAINER_OS_DETECTION=%s"
630
- "&NETDATA_SYSTEM_CPU_LOGICAL_CPU_COUNT=%s"
631
- "&NETDATA_SYSTEM_CPU_FREQ=%s"
632
- "&NETDATA_SYSTEM_TOTAL_RAM=%s"
633
- "&NETDATA_SYSTEM_TOTAL_DISK_SIZE=%s"
634
- "&NETDATA_PROTOCOL_VERSION=%s"
635
- " HTTP/1.1\r\n"
636
- "User-Agent: %s/%s\r\n"
637
- "Accept: */*\r\n\r\n"
638
- , host->rrdpush_send_api_key
639
- , host->hostname
640
- , host->registry_hostname
641
- , host->machine_guid
642
- , default_rrd_update_every
643
- , host->os
644
- , host->timezone
645
- , (host->tags) ? host->tags : ""
646
- , STREAMING_PROTOCOL_CURRENT_VERSION
647
- , se.os_name
648
- , se.os_id
649
- , (host->system_info->host_os_id_like) ? host->system_info->host_os_id_like : ""
650
- , se.os_version
651
- , (host->system_info->host_os_version_id) ? host->system_info->host_os_version_id : ""
652
- , (host->system_info->host_os_detection) ? host->system_info->host_os_detection : ""
653
- , se.kernel_name
654
- , se.kernel_version
655
- , (host->system_info->architecture) ? host->system_info->architecture : ""
656
- , (host->system_info->virtualization) ? host->system_info->virtualization : ""
657
- , (host->system_info->virt_detection) ? host->system_info->virt_detection : ""
658
- , (host->system_info->container) ? host->system_info->container : ""
659
- , (host->system_info->container_detection) ? host->system_info->container_detection : ""
660
- , (host->system_info->container_os_name) ? host->system_info->container_os_name : ""
661
- , (host->system_info->container_os_id) ? host->system_info->container_os_id : ""
662
- , (host->system_info->container_os_id_like) ? host->system_info->container_os_id_like : ""
663
- , (host->system_info->container_os_version) ? host->system_info->container_os_version : ""
664
- , (host->system_info->container_os_version_id) ? host->system_info->container_os_version_id : ""
665
- , (host->system_info->container_os_detection) ? host->system_info->container_os_detection : ""
666
- , (host->system_info->host_cores) ? host->system_info->host_cores : ""
667
- , (host->system_info->host_cpu_freq) ? host->system_info->host_cpu_freq : ""
668
- , (host->system_info->host_ram_total) ? host->system_info->host_ram_total : ""
669
- , (host->system_info->host_disk_space) ? host->system_info->host_disk_space : ""
670
- , STREAMING_PROTOCOL_VERSION
671
- , host->program_name
672
- , host->program_version
673
- );
674
- http[eol] = 0x00;
675
- rrdpush_clean_encoded(&se);
676
-
677
-#ifdef ENABLE_HTTPS
678
- if (!host->ssl.flags) {
679
- ERR_clear_error();
680
- SSL_set_connect_state(host->ssl.conn);
681
- int err = SSL_connect(host->ssl.conn);
682
- if (err != 1){
683
- err = SSL_get_error(host->ssl.conn, err);
684
- error("SSL cannot connect with the server: %s ",ERR_error_string((long)SSL_get_error(host->ssl.conn,err),NULL));
685
- if (netdata_use_ssl_on_stream == NETDATA_SSL_FORCE) {
686
- rrdpush_sender_thread_close_socket(host);
687
- return 0;
688
- }else {
689
- host->ssl.flags = NETDATA_SSL_NO_HANDSHAKE;
690
- }
691
- }
692
- else {
693
- if (netdata_use_ssl_on_stream == NETDATA_SSL_FORCE) {
694
- if (netdata_validate_server == NETDATA_SSL_VALID_CERTIFICATE) {
695
- if ( security_test_certificate(host->ssl.conn)) {
696
- error("Closing the stream connection, because the server SSL certificate is not valid.");
697
- rrdpush_sender_thread_close_socket(host);
698
- return 0;
699
- }
700
- }
701
- }
702
- }
703
- }
704
- if(send_timeout(&host->ssl,host->rrdpush_sender_socket, http, strlen(http), 0, timeout) == -1) {
705
-#else
706
- if(send_timeout(host->rrdpush_sender_socket, http, strlen(http), 0, timeout) == -1) {
707
-#endif
708
- error("STREAM %s [send to %s]: failed to send HTTP header to remote netdata.", host->hostname, connected_to);
709
- rrdpush_sender_thread_close_socket(host);
710
- return 0;
711
- }
712
-
713
- info("STREAM %s [send to %s]: waiting response from remote netdata...", host->hostname, connected_to);
714
-
715
- ssize_t received;
716
-#ifdef ENABLE_HTTPS
717
- received = recv_timeout(&host->ssl,host->rrdpush_sender_socket, http, HTTP_HEADER_SIZE, 0, timeout);
718
- if(received == -1) {
719
-#else
720
- received = recv_timeout(host->rrdpush_sender_socket, http, HTTP_HEADER_SIZE, 0, timeout);
721
- if(received == -1) {
722
-#endif
723
- error("STREAM %s [send to %s]: remote netdata does not respond.", host->hostname, connected_to);
724
- rrdpush_sender_thread_close_socket(host);
725
- return 0;
726
- }
727
-
728
- http[received] = '\0';
729
- int answer = -1;
730
- char *version_start = strchr(http, '=');
731
- uint32_t version;
732
- if(version_start) {
733
- version_start++;
734
- version = (uint32_t)strtol(version_start, NULL, 10);
735
- answer = memcmp(http, START_STREAMING_PROMPT_VN, (size_t)(version_start - http));
736
- if(!answer) {
737
- rrdpush_set_flags_to_newest_stream(host);
738
- host->stream_version = version;
739
- }
740
- } else {
741
- answer = memcmp(http, START_STREAMING_PROMPT_V2, strlen(START_STREAMING_PROMPT_V2));
742
- if(!answer) {
743
- version = 1;
744
- rrdpush_set_flags_to_newest_stream(host);
745
- }
746
- else {
747
- answer = memcmp(http, START_STREAMING_PROMPT, strlen(START_STREAMING_PROMPT));
748
- if(!answer) {
749
- version = 0;
750
- host->labels_flag |= LABEL_FLAG_STOP_STREAM;
751
- host->labels_flag &= ~LABEL_FLAG_UPDATE_STREAM;
752
- }
753
- }
754
- }
755
-
756
- if(answer != 0) {
757
- error("STREAM %s [send to %s]: server is not replying properly (is it a netdata?).", host->hostname, connected_to);
758
- rrdpush_sender_thread_close_socket(host);
759
- return 0;
760
- }
761
-
762
- info("STREAM %s [send to %s]: established communication with a master using protocol version %u - ready to send metrics..."
763
- , host->hostname
764
- , connected_to
765
- , version);
766
-
767
- if(sock_setnonblock(host->rrdpush_sender_socket) < 0)
768
- error("STREAM %s [send to %s]: cannot set non-blocking mode for socket.", host->hostname, connected_to);
769
-
770
- if(sock_enlarge_out(host->rrdpush_sender_socket) < 0)
771
- error("STREAM %s [send to %s]: cannot enlarge the socket buffer.", host->hostname, connected_to);
772
-
773
- debug(D_STREAM, "STREAM: Connected on fd %d...", host->rrdpush_sender_socket);
774
-
775
- return 1;
776
-}
777
-
778
-static void rrdpush_sender_thread_cleanup_callback(void *ptr) {
779
- RRDHOST *host = (RRDHOST *)ptr;
780
-
781
- rrdpush_buffer_lock(host);
782
- rrdhost_wrlock(host);
783
-
784
- info("STREAM %s [send]: sending thread cleans up...", host->hostname);
785
-
786
- rrdpush_sender_thread_close_socket(host);
787
-
788
- // close the pipe
789
- if(host->rrdpush_sender_pipe[PIPE_READ] != -1) {
790
- close(host->rrdpush_sender_pipe[PIPE_READ]);
791
- host->rrdpush_sender_pipe[PIPE_READ] = -1;
792
- }
793
-
794
- if(host->rrdpush_sender_pipe[PIPE_WRITE] != -1) {
795
- close(host->rrdpush_sender_pipe[PIPE_WRITE]);
796
- host->rrdpush_sender_pipe[PIPE_WRITE] = -1;
797
- }
798
-
799
- buffer_free(host->rrdpush_sender_buffer);
800
- host->rrdpush_sender_buffer = NULL;
801
-
802
- if(!host->rrdpush_sender_join) {
803
- info("STREAM %s [send]: sending thread detaches itself.", host->hostname);
804
- netdata_thread_detach(netdata_thread_self());
805
- }
806
-
807
- host->rrdpush_sender_spawn = 0;
808
-
809
- info("STREAM %s [send]: sending thread now exits.", host->hostname);
810
-
811
- rrdhost_unlock(host);
812
- rrdpush_buffer_unlock(host);
813
-}
814
-
815
-void *rrdpush_sender_thread(void *ptr) {
816
- RRDHOST *host = (RRDHOST *)ptr;
817
-
818
- if(!host->rrdpush_send_enabled || !host->rrdpush_send_destination || !*host->rrdpush_send_destination || !host->rrdpush_send_api_key || !*host->rrdpush_send_api_key) {
819
- error("STREAM %s [send]: thread created (task id %d), but host has streaming disabled.", host->hostname, gettid());
820
- return NULL;
821
- }
822
-
823
-#ifdef ENABLE_HTTPS
824
- if (netdata_use_ssl_on_stream & NETDATA_SSL_FORCE ){
825
- security_start_ssl(NETDATA_SSL_CONTEXT_STREAMING);
826
- security_location_for_context(netdata_client_ctx, netdata_ssl_ca_file, netdata_ssl_ca_path);
827
- }
828
-#endif
829
-
830
- info("STREAM %s [send]: thread created (task id %d)", host->hostname, gettid());
831
-
832
- int timeout = (int)appconfig_get_number(&stream_config, CONFIG_SECTION_STREAM, "timeout seconds", 60);
833
- int default_port = (int)appconfig_get_number(&stream_config, CONFIG_SECTION_STREAM, "default port", 19999);
834
- size_t max_size = (size_t)appconfig_get_number(&stream_config, CONFIG_SECTION_STREAM, "buffer size bytes", 1024 * 1024);
835
- unsigned int reconnect_delay = (unsigned int)appconfig_get_number(&stream_config, CONFIG_SECTION_STREAM, "reconnect delay seconds", 5);
836
- remote_clock_resync_iterations = (unsigned int)appconfig_get_number(&stream_config, CONFIG_SECTION_STREAM, "initial clock resync iterations", remote_clock_resync_iterations);
837
- char connected_to[CONNECTED_TO_SIZE + 1] = "";
838
-
839
- // initialize rrdpush globals
840
- host->rrdpush_sender_buffer = buffer_create(1);
841
- host->rrdpush_sender_connected = 0;
842
- if(pipe(host->rrdpush_sender_pipe) == -1) fatal("STREAM %s [send]: cannot create required pipe.", host->hostname);
843
-
844
- // initialize local variables
845
- size_t begin = 0;
846
- size_t reconnects_counter = 0;
847
- size_t sent_bytes = 0;
848
- size_t sent_bytes_on_this_connection = 0;
849
- size_t send_attempts = 0;
850
-
851
-
852
- time_t last_sent_t = 0;
853
- struct pollfd fds[2], *ifd, *ofd;
854
- nfds_t fdmax;
855
-
856
- ifd = &fds[0];
857
- ofd = &fds[1];
858
-
859
- size_t not_connected_loops = 0;
860
-
861
- netdata_thread_cleanup_push(rrdpush_sender_thread_cleanup_callback, host);
862
-
863
- for(; host->rrdpush_send_enabled && !netdata_exit ;) {
864
- // check for outstanding cancellation requests
865
- netdata_thread_testcancel();
866
-
867
- // if we don't have socket open, lets wait a bit
868
- if(unlikely(host->rrdpush_sender_socket == -1)) {
869
- send_attempts = 0;
870
-
871
- if(not_connected_loops == 0 && sent_bytes_on_this_connection > 0) {
872
- // fast re-connection on first disconnect
873
- sleep_usec(USEC_PER_MS * 500); // milliseconds
874
- }
875
- else {
876
- // slow re-connection on repeating errors
877
- sleep_usec(USEC_PER_SEC * reconnect_delay); // seconds
878
- }
879
-
880
- if(rrdpush_sender_thread_connect_to_master(host, default_port, timeout, &reconnects_counter, connected_to, CONNECTED_TO_SIZE)) {
881
- last_sent_t = now_monotonic_sec();
882
-
883
- // reset the buffer, to properly send charts and metrics
884
- rrdpush_sender_thread_data_flush(host);
885
-
886
- // send from the beginning
887
- begin = 0;
888
-
889
- // make sure the next reconnection will be immediate
890
- not_connected_loops = 0;
891
-
892
- // reset the bytes we have sent for this session
893
- sent_bytes_on_this_connection = 0;
894
-
895
- // let the data collection threads know we are ready
896
- host->rrdpush_sender_connected = 1;
897
- }
898
- else {
899
- // increase the failed connections counter
900
- not_connected_loops++;
901
-
902
- // reset the number of bytes sent
903
- sent_bytes_on_this_connection = 0;
904
- }
905
-
906
- // loop through
907
- continue;
908
- }
909
- else if(unlikely(now_monotonic_sec() - last_sent_t > timeout)) {
910
- error("STREAM %s [send to %s]: could not send metrics for %d seconds - closing connection - we have sent %zu bytes on this connection via %zu send attempts.", host->hostname, connected_to, timeout, sent_bytes_on_this_connection, send_attempts);
911
- rrdpush_sender_thread_close_socket(host);
912
- }
913
-
914
- ifd->fd = host->rrdpush_sender_pipe[PIPE_READ];
915
- ifd->events = POLLIN;
916
- ifd->revents = 0;
917
-
918
- ofd->fd = host->rrdpush_sender_socket;
919
- ofd->revents = 0;
920
- if(ofd->fd != -1 && begin < buffer_strlen(host->rrdpush_sender_buffer)) {
921
- debug(D_STREAM, "STREAM: Requesting data output on streaming socket %d...", ofd->fd);
922
- ofd->events = POLLOUT;
923
- fdmax = 2;
924
- send_attempts++;
925
- }
926
- else {
927
- debug(D_STREAM, "STREAM: Not requesting data output on streaming socket %d (nothing to send now)...", ofd->fd);
928
- ofd->events = 0;
929
- fdmax = 1;
930
- }
931
-
932
- debug(D_STREAM, "STREAM: Waiting for poll() events (current buffer length %zu bytes)...", buffer_strlen(host->rrdpush_sender_buffer));
933
- if(unlikely(netdata_exit)) break;
934
- int retval = poll(fds, fdmax, 1000);
935
- if(unlikely(netdata_exit)) break;
936
-
937
- if(unlikely(retval == -1)) {
938
- debug(D_STREAM, "STREAM: poll() failed (current buffer length %zu bytes)...", buffer_strlen(host->rrdpush_sender_buffer));
939
-
940
- if(errno == EAGAIN || errno == EINTR) {
941
- debug(D_STREAM, "STREAM: poll() failed with EAGAIN or EINTR...");
942
- }
943
- else {
944
- error("STREAM %s [send to %s]: failed to poll(). Closing socket.", host->hostname, connected_to);
945
- rrdpush_sender_thread_close_socket(host);
946
- }
947
-
948
- continue;
949
- }
950
- else if(likely(retval)) {
951
- if (ifd->revents & POLLIN || ifd->revents & POLLPRI) {
952
- debug(D_STREAM, "STREAM: Data added to send buffer (current buffer length %zu bytes)...", buffer_strlen(host->rrdpush_sender_buffer));
953
-
954
- char buffer[1000 + 1];
955
- if (read(host->rrdpush_sender_pipe[PIPE_READ], buffer, 1000) == -1)
956
- error("STREAM %s [send to %s]: cannot read from internal pipe.", host->hostname, connected_to);
957
- }
958
-
959
- if (ofd->revents & POLLOUT) {
960
- rrdpush_send_labels(host);
961
-
962
- if (begin < buffer_strlen(host->rrdpush_sender_buffer)) {
963
- debug(D_STREAM, "STREAM: Sending data (current buffer length %zu bytes, begin = %zu)...", buffer_strlen(host->rrdpush_sender_buffer), begin);
964
-
965
- // BEGIN RRDPUSH LOCKED SESSION
966
-
967
- // during this session, data collectors
968
- // will not be able to append data to our buffer
969
- // but the socket is in non-blocking mode
970
- // so, we will not block at send()
971
-
972
- netdata_thread_disable_cancelability();
973
-
974
- debug(D_STREAM, "STREAM: Getting exclusive lock on host...");
975
- rrdpush_buffer_lock(host);
976
-
977
- debug(D_STREAM, "STREAM: Sending data, starting from %zu, size %zu...", begin, buffer_strlen(host->rrdpush_sender_buffer));
978
- ssize_t ret;
979
-#ifdef ENABLE_HTTPS
980
- SSL *conn = host->ssl.conn ;
981
- if(conn && !host->ssl.flags) {
982
- ret = SSL_write(conn,&host->rrdpush_sender_buffer->buffer[begin], buffer_strlen(host->rrdpush_sender_buffer) - begin);
983
- } else {
984
- ret = send(host->rrdpush_sender_socket, &host->rrdpush_sender_buffer->buffer[begin], buffer_strlen(host->rrdpush_sender_buffer) - begin, MSG_DONTWAIT);
985
- }
986
-#else
987
- ret = send(host->rrdpush_sender_socket, &host->rrdpush_sender_buffer->buffer[begin], buffer_strlen(host->rrdpush_sender_buffer) - begin, MSG_DONTWAIT);
988
-#endif
989
- if (unlikely(ret == -1)) {
990
- if (errno != EAGAIN && errno != EINTR && errno != EWOULDBLOCK) {
991
- debug(D_STREAM, "STREAM: Send failed - closing socket...");
992
- error("STREAM %s [send to %s]: failed to send metrics - closing connection - we have sent %zu bytes on this connection.", host->hostname, connected_to, sent_bytes_on_this_connection);
993
- rrdpush_sender_thread_close_socket(host);
994
- }
995
- else {
996
- debug(D_STREAM, "STREAM: Send failed - will retry...");
997
- }
998
- }
999
- else if (likely(ret > 0)) {
1000
- // DEBUG - dump the string to see it
1001
- //char c = host->rrdpush_sender_buffer->buffer[begin + ret];
1002
- //host->rrdpush_sender_buffer->buffer[begin + ret] = '\0';
1003
- //debug(D_STREAM, "STREAM: sent from %zu to %zd:\n%s\n", begin, ret, &host->rrdpush_sender_buffer->buffer[begin]);
1004
- //host->rrdpush_sender_buffer->buffer[begin + ret] = c;
1005
-
1006
- sent_bytes_on_this_connection += ret;
1007
- sent_bytes += ret;
1008
- begin += ret;
1009
-
1010
- if (begin == buffer_strlen(host->rrdpush_sender_buffer)) {
1011
- // we send it all
1012
-
1013
- debug(D_STREAM, "STREAM: Sent %zd bytes (the whole buffer)...", ret);
1014
- buffer_flush(host->rrdpush_sender_buffer);
1015
- begin = 0;
1016
- }
1017
- else {
1018
- debug(D_STREAM, "STREAM: Sent %zd bytes (part of the data buffer)...", ret);
1019
- }
1020
-
1021
- last_sent_t = now_monotonic_sec();
1022
- }
1023
- else {
1024
- debug(D_STREAM, "STREAM: send() returned %zd - closing the socket...", ret);
1025
- error("STREAM %s [send to %s]: failed to send metrics (send() returned %zd) - closing connection - we have sent %zu bytes on this connection.",
1026
- host->hostname, connected_to, ret, sent_bytes_on_this_connection);
1027
- rrdpush_sender_thread_close_socket(host);
1028
- }
1029
-
1030
- debug(D_STREAM, "STREAM: Releasing exclusive lock on host...");
1031
- rrdpush_buffer_unlock(host);
1032
-
1033
- netdata_thread_enable_cancelability();
1034
-
1035
- // END RRDPUSH LOCKED SESSION
1036
- }
1037
- else {
1038
- debug(D_STREAM, "STREAM: we have sent the entire buffer, but we received POLLOUT...");
1039
- }
1040
- }
1041
-
1042
- if(host->rrdpush_sender_socket != -1) {
1043
- char *error = NULL;
1044
-
1045
- if (unlikely(ofd->revents & POLLERR))
1046
- error = "socket reports errors (POLLERR)";
1047
-
1048
- else if (unlikely(ofd->revents & POLLHUP))
1049
- error = "connection closed by remote end (POLLHUP)";
1050
-
1051
- else if (unlikely(ofd->revents & POLLNVAL))
1052
- error = "connection is invalid (POLLNVAL)";
1053
-
1054
- if(unlikely(error)) {
1055
- debug(D_STREAM, "STREAM: %s - closing socket...", error);
1056
- error("STREAM %s [send to %s]: %s - reopening socket - we have sent %zu bytes on this connection.", host->hostname, connected_to, error, sent_bytes_on_this_connection);
1057
- rrdpush_sender_thread_close_socket(host);
1058
- }
1059
- }
1060
- }
1061
- else {
1062
- debug(D_STREAM, "STREAM: poll() timed out.");
1063
- }
1064
-
1065
- // protection from overflow
1066
- if(buffer_strlen(host->rrdpush_sender_buffer) > max_size) {
1067
- debug(D_STREAM, "STREAM: Buffer is too big (%zu bytes), bigger than the max (%zu) - flushing it...", buffer_strlen(host->rrdpush_sender_buffer), max_size);
1068
- errno = 0;
1069
- error("STREAM %s [send to %s]: too many data pending - buffer is %zu bytes long, %zu unsent - we have sent %zu bytes in total, %zu on this connection. Closing connection to flush the data.", host->hostname, connected_to, host->rrdpush_sender_buffer->len, host->rrdpush_sender_buffer->len - begin, sent_bytes, sent_bytes_on_this_connection);
1070
- rrdpush_sender_thread_close_socket(host);
1071
- }
1072
- }
1073
-
1074
- netdata_thread_cleanup_pop(1);
1075
- return NULL;
1076
-}
1077
-
403
404
// ----------------------------------------------------------------------------
405
// rrdpush receiver thread
406
1082
-static void log_stream_connection(const char *client_ip, const char *client_port, const char *api_key, const char *machine_guid, const char *host, const char *msg) {
407
+void log_stream_connection(const char *client_ip, const char *client_port, const char *api_key, const char *machine_guid, const char *host, const char *msg) {
408
log_access("STREAM: %d '[%s]:%s' '%s' host '%s' api key '%s' machine guid '%s'", gettid(), client_ip, client_port, msg, host, api_key, machine_guid);
409
}
410
1086
-static int rrdpush_receive(int fd
1087
- , const char *key
1088
- , const char *hostname
1089
- , const char *registry_hostname
1090
- , const char *machine_guid
1091
- , const char *os
1092
- , const char *timezone
1093
- , const char *tags
1094
- , const char *program_name
1095
- , const char *program_version
1096
- , struct rrdhost_system_info *system_info
1097
- , int update_every
1098
- , char *client_ip
1099
- , char *client_port
1100
- , uint32_t stream_version
1101
-#ifdef ENABLE_HTTPS
1102
- , struct netdata_ssl *ssl
1103
-#endif
1104
-) {
1105
- RRDHOST *host;
1106
- int history = default_rrd_history_entries;
1107
- RRD_MEMORY_MODE mode = default_rrd_memory_mode;
1108
- int health_enabled = default_health_enabled;
1109
- int rrdpush_enabled = default_rrdpush_enabled;
1110
- char *rrdpush_destination = default_rrdpush_destination;
1111
- char *rrdpush_api_key = default_rrdpush_api_key;
1112
- char *rrdpush_send_charts_matching = default_rrdpush_send_charts_matching;
1113
- time_t alarms_delay = 60;
1114
-
1115
- update_every = (int)appconfig_get_number(&stream_config, machine_guid, "update every", update_every);
1116
- if(update_every < 0) update_every = 1;
1117
-
1118
- history = (int)appconfig_get_number(&stream_config, key, "default history", history);
1119
- history = (int)appconfig_get_number(&stream_config, machine_guid, "history", history);
1120
- if(history < 5) history = 5;
1121
-
1122
- mode = rrd_memory_mode_id(appconfig_get(&stream_config, key, "default memory mode", rrd_memory_mode_name(mode)));
1123
- mode = rrd_memory_mode_id(appconfig_get(&stream_config, machine_guid, "memory mode", rrd_memory_mode_name(mode)));
1124
-
1125
- health_enabled = appconfig_get_boolean_ondemand(&stream_config, key, "health enabled by default", health_enabled);
1126
- health_enabled = appconfig_get_boolean_ondemand(&stream_config, machine_guid, "health enabled", health_enabled);
1127
-
1128
- alarms_delay = appconfig_get_number(&stream_config, key, "default postpone alarms on connect seconds", alarms_delay);
1129
- alarms_delay = appconfig_get_number(&stream_config, machine_guid, "postpone alarms on connect seconds", alarms_delay);
1130
-
1131
- rrdpush_enabled = appconfig_get_boolean(&stream_config, key, "default proxy enabled", rrdpush_enabled);
1132
- rrdpush_enabled = appconfig_get_boolean(&stream_config, machine_guid, "proxy enabled", rrdpush_enabled);
1133
-
1134
- rrdpush_destination = appconfig_get(&stream_config, key, "default proxy destination", rrdpush_destination);
1135
- rrdpush_destination = appconfig_get(&stream_config, machine_guid, "proxy destination", rrdpush_destination);
1136
-
1137
- rrdpush_api_key = appconfig_get(&stream_config, key, "default proxy api key", rrdpush_api_key);
1138
- rrdpush_api_key = appconfig_get(&stream_config, machine_guid, "proxy api key", rrdpush_api_key);
1139
-
1140
- rrdpush_send_charts_matching = appconfig_get(&stream_config, key, "default proxy send charts matching", rrdpush_send_charts_matching);
1141
- rrdpush_send_charts_matching = appconfig_get(&stream_config, machine_guid, "proxy send charts matching", rrdpush_send_charts_matching);
1142
-
1143
- tags = appconfig_set_default(&stream_config, machine_guid, "host tags", (tags)?tags:"");
1144
- if(tags && !*tags) tags = NULL;
1145
-
1146
- if (strcmp(machine_guid, localhost->machine_guid) == 0) {
1147
- log_stream_connection(client_ip, client_port, key, machine_guid, hostname, "DENIED - ATTEMPT TO RECEIVE METRICS FROM MACHINE_GUID IDENTICAL TO MASTER");
1148
- error("STREAM %s [receive from %s:%s]: denied to receive metrics, machine GUID [%s] is my own. Did you copy the master/proxy machine guid to a slave?", hostname, client_ip, client_port, machine_guid);
1149
- close(fd);
1150
- return 1;
1151
- }
1152
-
1153
- /*
1154
- * Quick path for rejecting multiple connections. Don't take any locks so that progress is made. The same
1155
- * condition will be checked again below, while holding the global and host writer locks. Any potential false
1156
- * positives will not cause harm. Data hazards with host deconstruction will be handled when reference counting
1157
- * is implemented.
1158
- */
1159
- host = rrdhost_find_by_guid(machine_guid, 0);
1160
- if(host && host->connected_senders > 0) {
1161
- log_stream_connection(client_ip, client_port, key, host->machine_guid, host->hostname, "REJECTED - ALREADY CONNECTED");
1162
- info("STREAM %s [receive from [%s]:%s]: multiple streaming connections for the same host detected. Rejecting new connection.", host->hostname, client_ip, client_port);
1163
- close(fd);
1164
- return 0;
1165
- }
1166
-
1167
- host = rrdhost_find_or_create(
1168
- hostname
1169
- , registry_hostname
1170
- , machine_guid
1171
- , os
1172
- , timezone
1173
- , tags
1174
- , program_name
1175
- , program_version
1176
- , update_every
1177
- , history
1178
- , mode
1179
- , (unsigned int)(health_enabled != CONFIG_BOOLEAN_NO)
1180
- , (unsigned int)(rrdpush_enabled && rrdpush_destination && *rrdpush_destination && rrdpush_api_key && *rrdpush_api_key)
1181
- , rrdpush_destination
1182
- , rrdpush_api_key
1183
- , rrdpush_send_charts_matching
1184
- , system_info
1185
- );
1186
-
1187
- if(!host) {
1188
- close(fd);
1189
- log_stream_connection(client_ip, client_port, key, machine_guid, hostname, "FAILED - CANNOT ACQUIRE HOST");
1190
- error("STREAM %s [receive from [%s]:%s]: failed to find/create host structure.", hostname, client_ip, client_port);
1191
- return 1;
1192
- }
1193
-
1194
-#ifdef NETDATA_INTERNAL_CHECKS
1195
- info("STREAM %s [receive from [%s]:%s]: client willing to stream metrics for host '%s' with machine_guid '%s': update every = %d, history = %ld, memory mode = %s, health %s, tags '%s'"
1196
- , hostname
1197
- , client_ip
1198
- , client_port
1199
- , host->hostname
1200
- , host->machine_guid
1201
- , host->rrd_update_every
1202
- , host->rrd_history_entries
1203
- , rrd_memory_mode_name(host->rrd_memory_mode)
1204
- , (health_enabled == CONFIG_BOOLEAN_NO)?"disabled":((health_enabled == CONFIG_BOOLEAN_YES)?"enabled":"auto")
1205
- , host->tags?host->tags:""
1206
- );
1207
-#endif // NETDATA_INTERNAL_CHECKS
1208
-
1209
- struct plugind cd = {
1210
- .enabled = 1,
1211
- .update_every = default_rrd_update_every,
1212
- .pid = 0,
1213
- .serial_failures = 0,
1214
- .successful_collections = 0,
1215
- .obsolete = 0,
1216
- .started_t = now_realtime_sec(),
1217
- .next = NULL,
1218
- .version = 0,
1219
- };
1220
-
1221
- // put the client IP and port into the buffers used by plugins.d
1222
- snprintfz(cd.id, CONFIG_MAX_NAME, "%s:%s", client_ip, client_port);
1223
- snprintfz(cd.filename, FILENAME_MAX, "%s:%s", client_ip, client_port);
1224
- snprintfz(cd.fullfilename, FILENAME_MAX, "%s:%s", client_ip, client_port);
1225
- snprintfz(cd.cmd, PLUGINSD_CMD_MAX, "%s:%s", client_ip, client_port);
1226
-
1227
- info("STREAM %s [receive from [%s]:%s]: initializing communication...", host->hostname, client_ip, client_port);
1228
- char initial_response[HTTP_HEADER_SIZE];
1229
- if (stream_version > 1) {
1230
- info("STREAM %s [receive from [%s]:%s]: Netdata is using the stream version %u.", host->hostname, client_ip, client_port, stream_version);
1231
- sprintf(initial_response, "%s%u", START_STREAMING_PROMPT_VN, stream_version);
1232
- } else if (stream_version == 1) {
1233
- info("STREAM %s [receive from [%s]:%s]: Netdata is using the stream version %u.", host->hostname, client_ip, client_port, stream_version);
1234
- sprintf(initial_response, "%s", START_STREAMING_PROMPT_V2);
1235
- } else {
1236
- info("STREAM %s [receive from [%s]:%s]: Netdata is using first stream protocol.", host->hostname, client_ip, client_port);
1237
- sprintf(initial_response, "%s", START_STREAMING_PROMPT);
1238
- }
1239
- #ifdef ENABLE_HTTPS
1240
- host->stream_ssl.conn = ssl->conn;
1241
- host->stream_ssl.flags = ssl->flags;
1242
- if(send_timeout(ssl, fd, initial_response, strlen(initial_response), 0, 60) != (ssize_t)strlen(initial_response)) {
1243
-#else
1244
- if(send_timeout(fd, initial_response, strlen(initial_response), 0, 60) != strlen(initial_response)) {
1245
-#endif
1246
- log_stream_connection(client_ip, client_port, key, host->machine_guid, host->hostname, "FAILED - CANNOT REPLY");
1247
- error("STREAM %s [receive from [%s]:%s]: cannot send ready command.", host->hostname, client_ip, client_port);
1248
- close(fd);
1249
- return 0;
1250
- }
1251
-
1252
- // remove the non-blocking flag from the socket
1253
- if(sock_delnonblock(fd) < 0)
1254
- error("STREAM %s [receive from [%s]:%s]: cannot remove the non-blocking flag from socket %d", host->hostname, client_ip, client_port, fd);
1255
-
1256
- // convert the socket to a FILE *
1257
- FILE *fp = fdopen(fd, "r");
1258
- if(!fp) {
1259
- log_stream_connection(client_ip, client_port, key, host->machine_guid, host->hostname, "FAILED - SOCKET ERROR");
1260
- error("STREAM %s [receive from [%s]:%s]: failed to get a FILE for FD %d.", host->hostname, client_ip, client_port, fd);
1261
- close(fd);
1262
- return 0;
1263
- }
1264
-
1265
- rrdhost_wrlock(host);
1266
- if(host->connected_senders > 0) {
1267
- rrdhost_unlock(host);
1268
- log_stream_connection(client_ip, client_port, key, host->machine_guid, host->hostname, "REJECTED - ALREADY CONNECTED");
1269
- info("STREAM %s [receive from [%s]:%s]: multiple streaming connections for the same host detected. Rejecting new connection.", host->hostname, client_ip, client_port);
1270
- fclose(fp);
1271
- return 0;
1272
- }
1273
-
1274
- rrdhost_flag_clear(host, RRDHOST_FLAG_ORPHAN);
1275
- host->connected_senders++;
1276
- host->senders_disconnected_time = 0;
1277
- host->labels_flag = (stream_version > 0)?LABEL_FLAG_UPDATE_STREAM:LABEL_FLAG_STOP_STREAM;
1278
-
1279
- if(health_enabled != CONFIG_BOOLEAN_NO) {
1280
- if(alarms_delay > 0) {
1281
- host->health_delay_up_to = now_realtime_sec() + alarms_delay;
1282
- info("Postponing health checks for %ld seconds, on host '%s', because it was just connected."
1283
- , alarms_delay
1284
- , host->hostname
1285
- );
1286
- }
1287
- }
1288
- rrdhost_unlock(host);
1289
-
1290
- // call the plugins.d processor to receive the metrics
1291
- info("STREAM %s [receive from [%s]:%s]: receiving metrics...", host->hostname, client_ip, client_port);
1292
- log_stream_connection(client_ip, client_port, key, host->machine_guid, host->hostname, "CONNECTED");
1293
-
1294
- cd.version = stream_version;
1295
- size_t count = pluginsd_process(host, &cd, fp, 1);
1296
-
1297
- log_stream_connection(client_ip, client_port, key, host->machine_guid, host->hostname, "DISCONNECTED");
1298
- error("STREAM %s [receive from [%s]:%s]: disconnected (completed %zu updates).", host->hostname, client_ip, client_port, count);
1299
-
1300
- rrdhost_wrlock(host);
1301
- host->senders_disconnected_time = now_realtime_sec();
1302
- host->connected_senders--;
1303
- if(!host->connected_senders) {
1304
- rrdhost_flag_set(host, RRDHOST_FLAG_ORPHAN);
1305
- if(health_enabled == CONFIG_BOOLEAN_AUTO)
1306
- host->health_enabled = 0;
1307
- }
1308
- rrdhost_unlock(host);
1309
-
1310
- if(host->connected_senders == 0)
1311
- rrdpush_sender_thread_stop(host);
1312
-
1313
- // cleanup
1314
- fclose(fp);
1315
-
1316
- return (int)count;
1317
-}
1318
-
1319
-struct rrdpush_thread {
1320
- int fd;
1321
- char *key;
1322
- char *hostname;
1323
- char *registry_hostname;
1324
- char *machine_guid;
1325
- char *os;
1326
- char *timezone;
1327
- char *tags;
1328
- char *client_ip;
1329
- char *client_port;
1330
- char *program_name;
1331
- char *program_version;
1332
- struct rrdhost_system_info *system_info;
1333
- int update_every;
1334
- uint32_t stream_version;
1335
-#ifdef ENABLE_HTTPS
1336
- struct netdata_ssl ssl;
1337
-#endif
1338
-};
1339
-
1340
-static void rrdpush_receiver_thread_cleanup(void *ptr) {
1341
- static __thread int executed = 0;
1342
- if(!executed) {
1343
- executed = 1;
1344
- struct rrdpush_thread *rpt = (struct rrdpush_thread *) ptr;
1345
-
1346
- info("STREAM %s [receive from [%s]:%s]: receive thread ended (task id %d)", rpt->hostname, rpt->client_ip, rpt->client_port, gettid());
1347
-
1348
- freez(rpt->key);
1349
- freez(rpt->hostname);
1350
- freez(rpt->registry_hostname);
1351
- freez(rpt->machine_guid);
1352
- freez(rpt->os);
1353
- freez(rpt->timezone);
1354
- freez(rpt->tags);
1355
- freez(rpt->client_ip);
1356
- freez(rpt->client_port);
1357
- freez(rpt->program_name);
1358
- freez(rpt->program_version);
1359
-#ifdef ENABLE_HTTPS
1360
- if(rpt->ssl.conn){
1361
- SSL_free(rpt->ssl.conn);
1362
- }
1363
-#endif
1364
- freez(rpt);
1365
-
1366
- }
1367
-}
1368
-
1369
-static void *rrdpush_receiver_thread(void *ptr) {
1370
- netdata_thread_cleanup_push(rrdpush_receiver_thread_cleanup, ptr);
1371
-
1372
- struct rrdpush_thread *rpt = (struct rrdpush_thread *)ptr;
1373
- info("STREAM %s [%s]:%s: receive thread created (task id %d)", rpt->hostname, rpt->client_ip, rpt->client_port, gettid());
1374
-
1375
- rrdpush_receive(
1376
- rpt->fd
1377
- , rpt->key
1378
- , rpt->hostname
1379
- , rpt->registry_hostname
1380
- , rpt->machine_guid
1381
- , rpt->os
1382
- , rpt->timezone
1383
- , rpt->tags
1384
- , rpt->program_name
1385
- , rpt->program_version
1386
- , rpt->system_info
1387
- , rpt->update_every
1388
- , rpt->client_ip
1389
- , rpt->client_port
1390
- , rpt->stream_version
1391
-#ifdef ENABLE_HTTPS
1392
- , &rpt->ssl
1393
-#endif
1394
- );
1395
-
1396
- netdata_thread_cleanup_pop(1);
1397
- return NULL;
1398
-}
411
412
static void rrdpush_sender_thread_spawn(RRDHOST *host) {
413
rrdhost_wrlock(host);
416
char tag[NETDATA_THREAD_TAG_MAX + 1];
417
snprintfz(tag, NETDATA_THREAD_TAG_MAX, "STREAM_SENDER[%s]", host->hostname);
418
1407
- if(netdata_thread_create(&host->rrdpush_sender_thread, tag, NETDATA_THREAD_OPTION_JOINABLE, rrdpush_sender_thread, (void *) host))
419
+ if(netdata_thread_create(&host->rrdpush_sender_thread, tag, NETDATA_THREAD_OPTION_JOINABLE, rrdpush_sender_thread, (void *) host->sender))
420
error("STREAM %s [send]: failed to create new thread for client.", host->hostname);
421
else
422
host->rrdpush_sender_spawn = 1;
441
return 503;
442
}
443
1432
-int rrdpush_receiver_thread_spawn(RRDHOST *host, struct web_client *w, char *url) {
1433
- (void)host;
1434
-
444
+void *rrdpush_receiver_thread(void *ptr);
445
+int rrdpush_receiver_thread_spawn(struct web_client *w, char *url) {
446
info("clients wants to STREAM metrics.");
447
448
char *key = NULL, *hostname = NULL, *registry_hostname = NULL, *machine_guid = NULL, *os = "unknown", *timezone = "unknown", *tags = NULL;
604
netdata_mutex_unlock(&stream_rate_mutex);
605
}
606
1596
- struct rrdpush_thread *rpt = callocz(1, sizeof(struct rrdpush_thread));
607
+ /*
608
+ * Quick path for rejecting multiple connections. The lock taken is fine-grained - it only protects the receiver
609
+ * pointer within the host (if a host exists). This protects against multiple concurrent web requests hitting
610
+ * separate threads within the web-server and landing here. The lock guards the thread-shutdown sequence that
611
+ * detaches the receiver from the host. If the host is being created (first time-access) then we also use the
612
+ * lock to prevent race-hazard (two threads try to create the host concurrently, one wins and the other does a
613
+ * lookup to the now-attached structure).
614
+ */
615
+ struct receiver_state *rpt = callocz(1, sizeof(*rpt));
616
+ RRDHOST *host = rrdhost_find_by_guid(machine_guid, 0);
617
+ if (host) {
618
+ netdata_mutex_lock(&host->receiver_lock);
619
+ if (host->receiver != NULL) {
620
+ time_t age = now_realtime_sec() - host->receiver->last_msg_t;
621
+ if (age > 30) {
622
+ host->receiver->shutdown = 1;
623
+ shutdown(host->receiver->fd, SHUT_RDWR);
624
+ host->receiver = NULL; // Thread holds reference to structure
625
+ info("STREAM %s [receive from [%s]:%s]: multiple connections for same host detected - existing connection is dead (%ld sec), accepting new connection.", host->hostname, w->client_ip, w->client_port, age);
626
+ }
627
+ else {
628
+ netdata_mutex_unlock(&host->receiver_lock);
629
+ log_stream_connection(w->client_ip, w->client_port, key, host->machine_guid, host->hostname,
630
+ "REJECTED - ALREADY CONNECTED");
631
+ info("STREAM %s [receive from [%s]:%s]: multiple connections for same host detected - existing connection is active (within last %ld sec), rejecting new connection.", host->hostname, w->client_ip, w->client_port, age);
632
+ // Have not set WEB_CLIENT_FLAG_DONT_CLOSE_SOCKET - caller should clean up
633
+ buffer_flush(w->response.data);
634
+ buffer_strcat(w->response.data, "This GUID is already streaming to this server");
635
+ freez(rpt);
636
+ return 409;
637
+ }
638
+ }
639
+ host->receiver = rpt;
640
+ netdata_mutex_unlock(&host->receiver_lock);
641
+ }
642
+
643
+ rpt->last_msg_t = now_realtime_sec();
644
+
645
+ rpt->host = host;
646
rpt->fd = w->ifd;
647
rpt->key = strdupz(key);
648
rpt->hostname = strdupz(hostname);