summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--CMakeLists.txt2
-rw-r--r--Makefile.am2
-rw-r--r--libnetdata/avl/avl.h5
-rw-r--r--libnetdata/dictionary/dictionary.c4
-rw-r--r--libnetdata/dictionary/dictionary.h1
-rw-r--r--libnetdata/socket/socket.h12
-rw-r--r--libnetdata/string/string.c226
-rw-r--r--registry/registry.c135
-rw-r--r--registry/registry_db.c241
-rw-r--r--registry/registry_init.c167
-rw-r--r--registry/registry_internals.c50
-rw-r--r--registry/registry_internals.h30
-rw-r--r--registry/registry_log.c6
-rw-r--r--registry/registry_machine.c64
-rw-r--r--registry/registry_machine.h15
-rw-r--r--registry/registry_person.c142
-rw-r--r--registry/registry_person.h30
-rw-r--r--registry/registry_url.c88
-rw-r--r--registry/registry_url.h35
-rw-r--r--web/api/web_api.c31
-rw-r--r--web/api/web_api.h5
-rw-r--r--web/api/web_api_v1.c23
-rw-r--r--web/api/web_api_v2.c151
23 files changed, 868 insertions, 597 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 866cb5d8ba..0ae2cd3e6b 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -700,8 +700,6 @@ set(REGISTRY_PLUGIN_FILES
registry/registry_machine.h
registry/registry_person.c
registry/registry_person.h
- registry/registry_url.c
- registry/registry_url.h
)
set(STATSD_PLUGIN_FILES
diff --git a/Makefile.am b/Makefile.am
index 26e345bbf4..5998a7bea0 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -661,8 +661,6 @@ REGISTRY_PLUGIN_FILES = \
registry/registry_machine.h \
registry/registry_person.c \
registry/registry_person.h \
- registry/registry_url.c \
- registry/registry_url.h \
$(NULL)
STATSD_PLUGIN_FILES = \
diff --git a/libnetdata/avl/avl.h b/libnetdata/avl/avl.h
index 49dea3cbae..595d6ec6c0 100644
--- a/libnetdata/avl/avl.h
+++ b/libnetdata/avl/avl.h
@@ -24,6 +24,11 @@ typedef struct avl_element {
signed char avl_balance; /* Balance factor. */
} avl_t;
+typedef struct __attribute__((packed)) avl_element_packed {
+ struct avl_element *avl_link[2]; /* Subtrees. */
+ signed char avl_balance; /* Balance factor. */
+} avl_t_packed;
+
/* An AVL tree */
typedef struct avl_tree_type {
avl_t *root;
diff --git a/libnetdata/dictionary/dictionary.c b/libnetdata/dictionary/dictionary.c
index f18a7f87f9..bb76e6f6f1 100644
--- a/libnetdata/dictionary/dictionary.c
+++ b/libnetdata/dictionary/dictionary.c
@@ -369,10 +369,6 @@ size_t dictionary_referenced_items(DICTIONARY *dict) {
return referenced_items;
}
-long int dictionary_stats_for_registry(DICTIONARY *dict) {
- if(unlikely(!dict)) return 0;
- return (dict->stats->memory.index + dict->stats->memory.dict);
-}
void dictionary_version_increment(DICTIONARY *dict) {
__atomic_fetch_add(&dict->version, 1, __ATOMIC_RELAXED);
}
diff --git a/libnetdata/dictionary/dictionary.h b/libnetdata/dictionary/dictionary.h
index fccdbf506b..eea14d3fae 100644
--- a/libnetdata/dictionary/dictionary.h
+++ b/libnetdata/dictionary/dictionary.h
@@ -310,7 +310,6 @@ void dictionary_foreach_unlock(DICTFE *dfe);
size_t dictionary_version(DICTIONARY *dict);
size_t dictionary_entries(DICTIONARY *dict);
size_t dictionary_referenced_items(DICTIONARY *dict);
-long int dictionary_stats_for_registry(DICTIONARY *dict);
// for all cases that the caller does not provide a stats structure, this is where they are accumulated.
extern struct dictionary_stats dictionary_stats_category_other;
diff --git a/libnetdata/socket/socket.h b/libnetdata/socket/socket.h
index 0e29711e04..3a5b7b4a20 100644
--- a/libnetdata/socket/socket.h
+++ b/libnetdata/socket/socket.h
@@ -11,7 +11,7 @@
typedef enum web_client_acl {
WEB_CLIENT_ACL_NONE = (0),
- WEB_CLIENT_ACL_NOCHECK = (0),
+ WEB_CLIENT_ACL_NOCHECK = (0), // Don't check anything - this should work on all channels
WEB_CLIENT_ACL_DASHBOARD = (1 << 0),
WEB_CLIENT_ACL_REGISTRY = (1 << 1),
WEB_CLIENT_ACL_BADGE = (1 << 2),
@@ -23,9 +23,17 @@ typedef enum web_client_acl {
WEB_CLIENT_ACL_SSL_DEFAULT = (1 << 8),
WEB_CLIENT_ACL_ACLK = (1 << 9),
WEB_CLIENT_ACL_WEBRTC = (1 << 10),
+ WEB_CLIENT_ACL_BEARER_OPTIONAL = (1 << 11), // allow unprotected access if bearer is not enabled in netdata
+ WEB_CLIENT_ACL_BEARER_REQUIRED = (1 << 12), // allow access only if a valid bearer is used
} WEB_CLIENT_ACL;
-#define WEB_CLIENT_ACL_DASHBOARD_ACLK_WEBRTC (WEB_CLIENT_ACL_DASHBOARD | WEB_CLIENT_ACL_ACLK | WEB_CLIENT_ACL_WEBRTC)
+#define WEB_CLIENT_ACL_DASHBOARD_ACLK_WEBRTC (WEB_CLIENT_ACL_DASHBOARD | WEB_CLIENT_ACL_ACLK | WEB_CLIENT_ACL_WEBRTC | WEB_CLIENT_ACL_BEARER_OPTIONAL)
+
+#ifdef NETDATA_DEV_MODE
+#define ACL_DEV_OPEN_ACCESS WEB_CLIENT_ACL_DASHBOARD
+#else
+#define ACL_DEV_OPEN_ACCESS 0
+#endif
#define WEB_CLIENT_ACL_ALL 0xFFFF
diff --git a/libnetdata/string/string.c b/libnetdata/string/string.c
index 159f8a6a84..373d0c24c5 100644
--- a/libnetdata/string/string.c
+++ b/libnetdata/string/string.c
@@ -8,6 +8,11 @@ typedef int32_t REFCOUNT;
// ----------------------------------------------------------------------------
// STRING implementation - dedup all STRING
+#define STRING_PARTITION_SHIFTS (0)
+#define STRING_PARTITIONS (256 >> STRING_PARTITION_SHIFTS)
+#define string_partition_str(str) ((uint8_t)((str)[0]) >> STRING_PARTITION_SHIFTS)
+#define string_partition(string) (string_partition_str((string)->str))
+
struct netdata_string {
uint32_t length; // the string length including the terminating '\0'
@@ -18,20 +23,22 @@ struct netdata_string {
const char str[]; // the string itself, is appended to this structure
};
-static struct string_hashtable {
- Pvoid_t JudyHSArray; // the Judy array - hashtable
- netdata_rwlock_t rwlock; // the R/W lock to protect the Judy array
+static struct string_partition {
+ RW_SPINLOCK spinlock; // the R/W spinlock to protect the Judy array
- long int entries; // the number of entries in the index
- long int active_references; // the number of active references alive
- long int memory; // the memory used, without the JudyHS index
+ Pvoid_t JudyHSArray; // the Judy array - hashtable
- size_t inserts; // the number of successful inserts to the index
- size_t deletes; // the number of successful deleted from the index
size_t searches; // the number of successful searches in the index
size_t duplications; // when a string is referenced
size_t releases; // when a string is unreferenced
+ size_t inserts; // the number of successful inserts to the index
+ size_t deletes; // the number of successful deleted from the index
+
+ long int entries; // the number of entries in the index
+ long int active_references; // the number of active references alive
+ long int memory; // the memory used, without the JudyHS index
+
#ifdef NETDATA_INTERNAL_CHECKS
// internal statistics
size_t found_deleted_on_search;
@@ -41,50 +48,45 @@ static struct string_hashtable {
size_t spins;
#endif
-} string_base = {
- .JudyHSArray = NULL,
- .rwlock = NETDATA_RWLOCK_INITIALIZER,
-};
+} string_base[STRING_PARTITIONS] = { 0 };
#ifdef NETDATA_INTERNAL_CHECKS
-#define string_internal_stats_add(var, val) __atomic_add_fetch(&string_base.var, val, __ATOMIC_RELAXED)
+#define string_internal_stats_add(partition, var, val) __atomic_add_fetch(&string_base[partition].var, val, __ATOMIC_RELAXED)
#else
-#define string_internal_stats_add(var, val) do {;} while(0)
+#define string_internal_stats_add(partition, var, val) do {;} while(0)
#endif
-#define string_stats_atomic_increment(var) __atomic_add_fetch(&string_base.var, 1, __ATOMIC_RELAXED)
-#define string_stats_atomic_decrement(var) __atomic_sub_fetch(&string_base.var, 1, __ATOMIC_RELAXED)
+#define string_stats_atomic_increment(partition, var) __atomic_add_fetch(&string_base[partition].var, 1, __ATOMIC_RELAXED)
+#define string_stats_atomic_decrement(partition, var) __atomic_sub_fetch(&string_base[partition].var, 1, __ATOMIC_RELAXED)
void string_statistics(size_t *inserts, size_t *deletes, size_t *searches, size_t *entries, size_t *references, size_t *memory, size_t *duplications, size_t *releases) {
- if(inserts)
- *inserts = string_base.inserts;
-
- if(deletes)
- *deletes = string_base.deletes;
-
- if(searches)
- *searches = string_base.searches;
-
- if(entries)
- *entries = (size_t)string_base.entries;
-
- if(references)
- *references = (size_t)string_base.active_references;
-
- if(memory)
- *memory = (size_t)string_base.memory;
-
- if(duplications)
- *duplications = string_base.duplications;
-
- if(releases)
- *releases = string_base.releases;
+ if (inserts) *inserts = 0;
+ if (deletes) *deletes = 0;
+ if (searches) *searches = 0;
+ if (entries) *entries = 0;
+ if (references) *references = 0;
+ if (memory) *memory = 0;
+ if (duplications) *duplications = 0;
+ if (releases) *releases = 0;
+
+ for(size_t i = 0; i < STRING_PARTITIONS ;i++) {
+ if (inserts) *inserts += string_base[i].inserts;
+ if (deletes) *deletes += string_base[i].deletes;
+ if (searches) *searches += string_base[i].searches;
+ if (entries) *entries += (size_t) string_base[i].entries;
+ if (references) *references += (size_t) string_base[i].active_references;
+ if (memory) *memory += (size_t) string_base[i].memory;
+ if (duplications) *duplications += string_base[i].duplications;
+ if (releases) *releases += string_base[i].releases;
+ }
}
#define string_entry_acquire(se) __atomic_add_fetch(&((se)->refcount), 1, __ATOMIC_SEQ_CST);
#define string_entry_release(se) __atomic_sub_fetch(&((se)->refcount), 1, __ATOMIC_SEQ_CST);
static inline bool string_entry_check_and_acquire(STRING *se) {
+ uint8_t partition = string_partition(se);
+
REFCOUNT expected, desired, count = 0;
expected = __atomic_load_n(&se->refcount, __ATOMIC_SEQ_CST);
@@ -96,7 +98,7 @@ static inline bool string_entry_check_and_acquire(STRING *se) {
// We cannot use this.
// The reference counter reached value zero,
// so another thread is deleting this.
- string_internal_stats_add(spins, count - 1);
+ string_internal_stats_add(partition, spins, count - 1);
return false;
}
@@ -104,11 +106,11 @@ static inline bool string_entry_check_and_acquire(STRING *se) {
} while(!__atomic_compare_exchange_n(&se->refcount, &expected, desired, false, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST));
- string_internal_stats_add(spins, count - 1);
+ string_internal_stats_add(partition, spins, count - 1);
// statistics
// string_base.active_references is altered at the in string_strdupz() and string_freez()
- string_stats_atomic_increment(duplications);
+ string_stats_atomic_increment(partition, duplications);
return true;
}
@@ -123,9 +125,11 @@ STRING *string_dup(STRING *string) {
string_entry_acquire(string);
+ uint8_t partition = string_partition(string);
+
// statistics
- string_stats_atomic_increment(active_references);
- string_stats_atomic_increment(duplications);
+ string_stats_atomic_increment(partition, active_references);
+ string_stats_atomic_increment(partition, duplications);
return string;
}
@@ -134,26 +138,28 @@ STRING *string_dup(STRING *string) {
static inline STRING *string_index_search(const char *str, size_t length) {
STRING *string;
+ uint8_t partition = string_partition_str(str);
+
// Find the string in the index
// With a read-lock so that multiple readers can use the index concurrently.
- netdata_rwlock_rdlock(&string_base.rwlock);
+ rw_spinlock_read_lock(&string_base[partition].spinlock);
Pvoid_t *Rc;
- Rc = JudyHSGet(string_base.JudyHSArray, (void *)str, length);
+ Rc = JudyHSGet(string_base[partition].JudyHSArray, (void *)str, length - 1);
if(likely(Rc)) {
// found in the hash table
string = *Rc;
if(string_entry_check_and_acquire(string)) {
// we can use this entry
- string_internal_stats_add(found_available_on_search, 1);
+ string_internal_stats_add(partition, found_available_on_search, 1);
}
else {
// this entry is about to be deleted by another thread
// do not touch it, let it go...
string = NULL;
- string_internal_stats_add(found_deleted_on_search, 1);
+ string_internal_stats_add(partition, found_deleted_on_search, 1);
}
}
else {
@@ -161,8 +167,8 @@ static inline STRING *string_index_search(const char *str, size_t length) {
string = NULL;
}
- string_stats_atomic_increment(searches);
- netdata_rwlock_unlock(&string_base.rwlock);
+ string_stats_atomic_increment(partition, searches);
+ rw_spinlock_read_unlock(&string_base[partition].spinlock);
return string;
}
@@ -175,12 +181,14 @@ static inline STRING *string_index_search(const char *str, size_t length) {
static inline STRING *string_index_insert(const char *str, size_t length) {
STRING *string;
- netdata_rwlock_wrlock(&string_base.rwlock);
+ uint8_t partition = string_partition_str(str);
+
+ rw_spinlock_write_lock(&string_base[partition].spinlock);
STRING **ptr;
{
JError_t J_Error;
- Pvoid_t *Rc = JudyHSIns(&string_base.JudyHSArray, (void *)str, length, &J_Error);
+ Pvoid_t *Rc = JudyHSIns(&string_base[partition].JudyHSArray, (void *)str, length - 1, &J_Error);
if (unlikely(Rc == PJERR)) {
fatal(
"STRING: Cannot insert entry with name '%s' to JudyHS, JU_ERRNO_* == %u, ID == %d",
@@ -199,9 +207,9 @@ static inline STRING *string_index_insert(const char *str, size_t length) {
string->length = length;
string->refcount = 1;
*ptr = string;
- string_base.inserts++;
- string_base.entries++;
- string_base.memory += (long)(mem_size + JUDYHS_INDEX_SIZE_ESTIMATE(length));
+ string_base[partition].inserts++;
+ string_base[partition].entries++;
+ string_base[partition].memory += (long)(mem_size + JUDYHS_INDEX_SIZE_ESTIMATE(length));
}
else {
// the item is already in the index
@@ -209,25 +217,27 @@ static inline STRING *string_index_insert(const char *str, size_t length) {
if(string_entry_check_and_acquire(string)) {
// we can use this entry
- string_internal_stats_add(found_available_on_insert, 1);
+ string_internal_stats_add(partition, found_available_on_insert, 1);
}
else {
// this entry is about to be deleted by another thread
// do not touch it, let it go...
string = NULL;
- string_internal_stats_add(found_deleted_on_insert, 1);
+ string_internal_stats_add(partition, found_deleted_on_insert, 1);
}
- string_stats_atomic_increment(searches);
+ string_stats_atomic_increment(partition, searches);
}
- netdata_rwlock_unlock(&string_base.rwlock);
+ rw_spinlock_write_unlock(&string_base[partition].spinlock);
return string;
}
// delete an entry from the index
static inline void string_index_delete(STRING *string) {
- netdata_rwlock_wrlock(&string_base.rwlock);
+ uint8_t partition = string_partition(string);
+
+ rw_spinlock_write_lock(&string_base[partition].spinlock);
#ifdef NETDATA_INTERNAL_CHECKS
if(unlikely(__atomic_load_n(&string->refcount, __ATOMIC_SEQ_CST) != 0))
@@ -236,9 +246,9 @@ static inline void string_index_delete(STRING *string) {
bool deleted = false;
- if (likely(string_base.JudyHSArray)) {
+ if (likely(string_base[partition].JudyHSArray)) {
JError_t J_Error;
- int ret = JudyHSDel(&string_base.JudyHSArray, (void *)string->str, string->length, &J_Error);
+ int ret = JudyHSDel(&string_base[partition].JudyHSArray, (void *)string->str, string->length - 1, &J_Error);
if (unlikely(ret == JERR)) {
netdata_log_error(
"STRING: Cannot delete entry with name '%s' from JudyHS, JU_ERRNO_* == %u, ID == %d",
@@ -253,18 +263,20 @@ static inline void string_index_delete(STRING *string) {
netdata_log_error("STRING: tried to delete '%s' that is not in the index. Ignoring it.", string->str);
else {
size_t mem_size = sizeof(STRING) + string->length;
- string_base.deletes++;
- string_base.entries--;
- string_base.memory -= (long)(mem_size + JUDYHS_INDEX_SIZE_ESTIMATE(string->length));
+ string_base[partition].deletes++;
+ string_base[partition].entries--;
+ string_base[partition].memory -= (long)(mem_size + JUDYHS_INDEX_SIZE_ESTIMATE(string->length));
freez(string);
}
- netdata_rwlock_unlock(&string_base.rwlock);
+ rw_spinlock_write_unlock(&string_base[partition].spinlock);
}
STRING *string_strdupz(const char *str) {
if(unlikely(!str || !*str)) return NULL;
+ uint8_t partition = string_partition_str(str);
+
size_t length = strlen(str) + 1;
STRING *string = string_index_search(str, length);
@@ -277,7 +289,7 @@ STRING *string_strdupz(const char *str) {
}
// statistics
- string_stats_atomic_increment(active_references);
+ string_stats_atomic_increment(partition, active_references);
return string;
}
@@ -285,6 +297,7 @@ STRING *string_strdupz(const char *str) {
void string_freez(STRING *string) {
if(unlikely(!string)) return;
+ uint8_t partition = string_partition(string);
REFCOUNT refcount = string_entry_release(string);
#ifdef NETDATA_INTERNAL_CHECKS
@@ -296,8 +309,8 @@ void string_freez(STRING *string) {
string_index_delete(string);
// statistics
- string_stats_atomic_decrement(active_references);
- string_stats_atomic_increment(releases);
+ string_stats_atomic_decrement(partition, active_references);
+ string_stats_atomic_increment(partition, releases);
}
inline size_t string_strlen(STRING *string) {
@@ -405,6 +418,54 @@ static void string_unittest_free_char_pp(char **pp, size_t entries) {
freez(pp);
}
+static long unittest_string_entries(void) {
+ long entries = 0;
+ for(size_t p = 0; p < STRING_PARTITIONS ;p++)
+ entries += string_base[p].entries;
+
+ return entries;
+}
+
+#ifdef NETDATA_INTERNAL_CHECKS
+
+static size_t unittest_string_found_deleted_on_search(void) {
+ size_t entries = 0;
+ for(size_t p = 0; p < STRING_PARTITIONS ;p++)
+ entries += string_base[p].found_deleted_on_search;
+
+ return entries;
+}
+static size_t unittest_string_found_available_on_search(void) {
+ size_t entries = 0;
+ for(size_t p = 0; p < STRING_PARTITIONS ;p++)
+ entries += string_base[p].found_available_on_search;
+
+ return entries;
+}
+static size_t unittest_string_found_deleted_on_insert(void) {
+ size_t entries = 0;
+ for(size_t p = 0; p < STRING_PARTITIONS ;p++)
+ entries += string_base[p].found_deleted_on_insert;
+
+ return entries;
+}
+static size_t unittest_string_found_available_on_insert(void) {
+ size_t entries = 0;
+ for(size_t p = 0; p < STRING_PARTITIONS ;p++)
+ entries += string_base[p].found_available_on_insert;
+
+ return entries;
+}
+static size_t unittest_string_spins(void) {
+ size_t entries = 0;
+ for(size_t p = 0; p < STRING_PARTITIONS ;p++)
+ entries += string_base[p].spins;
+
+ return entries;
+}
+
+#endif // NETDATA_INTERNAL_CHECKS
+
int string_unittest(size_t entries) {
size_t errors = 0;
@@ -413,7 +474,7 @@ int string_unittest(size_t entries) {
// check string
{
- long int string_entries_starting = string_base.entries;
+ long entries_starting = unittest_string_entries();
fprintf(stderr, "\nChecking strings...\n");
@@ -496,9 +557,10 @@ int string_unittest(size_t entries) {
freez(strings);
- if(string_base.entries != string_entries_starting + 2) {
+ if(unittest_string_entries() != entries_starting + 2) {
errors++;
- fprintf(stderr, "ERROR: strings dictionary should have %ld items but it has %ld\n", string_entries_starting + 2, string_base.entries);
+ fprintf(stderr, "ERROR: strings dictionary should have %ld items but it has %ld\n",
+ entries_starting + 2, unittest_string_entries());
}
else
fprintf(stderr, "OK: strings dictionary has 2 items\n");
@@ -551,11 +613,11 @@ int string_unittest(size_t entries) {
};
#ifdef NETDATA_INTERNAL_CHECKS
- size_t ofound_deleted_on_search = string_base.found_deleted_on_search,
- ofound_available_on_search = string_base.found_available_on_search,
- ofound_deleted_on_insert = string_base.found_deleted_on_insert,
- ofound_available_on_insert = string_base.found_available_on_insert,
- ospins = string_base.spins;
+ size_t ofound_deleted_on_search = unittest_string_found_deleted_on_search(),
+ ofound_available_on_search = unittest_string_found_available_on_search(),
+ ofound_deleted_on_insert = unittest_string_found_deleted_on_insert(),
+ ofound_available_on_insert = unittest_string_found_available_on_insert(),
+ ospins = unittest_string_spins();
#endif
size_t oinserts, odeletes, osearches, oentries, oreferences, omemory, oduplications, oreleases;
@@ -592,11 +654,11 @@ int string_unittest(size_t entries) {
inserts - oinserts, deletes - odeletes, searches - osearches, sentries - oentries, references - oreferences, memory - omemory, duplications - oduplications, releases - oreleases);
#ifdef NETDATA_INTERNAL_CHECKS
- size_t found_deleted_on_search = string_base.found_deleted_on_search,
- found_available_on_search = string_base.found_available_on_search,
- found_deleted_on_insert = string_base.found_deleted_on_insert,
- found_available_on_insert = string_base.found_available_on_insert,
- spins = string_base.spins;
+ size_t found_deleted_on_search = unittest_string_found_deleted_on_search(),
+ found_available_on_search = unittest_string_found_available_on_search(),
+ found_deleted_on_insert = unittest_string_found_deleted_on_insert(),
+ found_available_on_insert = unittest_string_found_available_on_insert(),
+ spins = unittest_string_spins();
fprintf(stderr, "on insert: %zu ok + %zu deleted\non search: %zu ok + %zu deleted\nspins: %zu\n",
found_available_on_insert - ofound_available_on_insert,
diff --git a/registry/registry.c b/registry/registry.c
index f8de470eb8..04edb95c0d 100644
--- a/registry/registry.c
+++ b/registry/registry.c
@@ -8,6 +8,10 @@
#define REGISTRY_STATUS_FAILED "failed"
#define REGISTRY_STATUS_DISABLED "disabled"
+bool registry_is_valid_url(const char *url) {
+ return url && (*url == 'h' || *url == '*');
+}
+
// ----------------------------------------------------------------------------
// REGISTRY concurrency locking
@@ -23,19 +27,19 @@ static inline void registry_unlock(void) {
// COOKIES
static void registry_set_cookie(struct web_client *w, const char *guid) {
- char edate[100];
+ char e_date[100];
time_t et = now_realtime_sec() + registry.persons_expiration;
- struct tm etmbuf, *etm = gmtime_r(&et, &etmbuf);
- strftime(edate, sizeof(edate), "%a, %d %b %Y %H:%M:%S %Z", etm);
+ struct tm e_tm_buf, *etm = gmtime_r(&et, &e_tm_buf);
+ strftime(e_date, sizeof(e_date), "%a, %d %b %Y %H:%M:%S %Z", etm);
- buffer_sprintf(w->response.header, "Set-Cookie: " NETDATA_REGISTRY_COOKIE_NAME "=%s; Expires=%s\r\n", guid, edate);
+ buffer_sprintf(w->response.header, "Set-Cookie: " NETDATA_REGISTRY_COOKIE_NAME "=%s; Expires=%s\r\n", guid, e_date);
if(registry.enable_cookies_samesite_secure)
- buffer_sprintf(w->response.header, "Set-Cookie: " NETDATA_REGISTRY_COOKIE_NAME "=%s; Expires=%s; SameSite=None; Secure\r\n", guid, edate);
+ buffer_sprintf(w->response.header, "Set-Cookie: " NETDATA_REGISTRY_COOKIE_NAME "=%s; Expires=%s; SameSite=None; Secure\r\n", guid, e_date);
if(registry.registry_domain && *registry.registry_domain) {
- buffer_sprintf(w->response.header, "Set-Cookie: " NETDATA_REGISTRY_COOKIE_NAME "=%s; Expires=%s; Domain=%s\r\n", guid, edate, registry.registry_domain);
+ buffer_sprintf(w->response.header, "Set-Cookie: " NETDATA_REGISTRY_COOKIE_NAME "=%s; Expires=%s; Domain=%s\r\n", guid, e_date, registry.registry_domain);
if(registry.enable_cookies_samesite_secure)
- buffer_sprintf(w->response.header, "Set-Cookie: " NETDATA_REGISTRY_COOKIE_NAME "=%s; Expires=%s; Domain=%s; SameSite=None; Secure\r\n", guid, edate, registry.registry_domain);
+ buffer_sprintf(w->response.header, "Set-Cookie: " NETDATA_REGISTRY_COOKIE_NAME "=%s; Expires=%s; Domain=%s; SameSite=None; Secure\r\n", guid, e_date, registry.registry_domain);
}
w->response.has_cookies = true;
@@ -84,37 +88,41 @@ struct registry_json_walk_person_urls_callback {
int count;
};
+static STRING *asterisks = NULL;
+
// callback for rendering PERSON_URLs
-static int registry_json_person_url_callback(void *entry, void *data) {
- REGISTRY_PERSON_URL *pu = (REGISTRY_PERSON_URL *)entry;
- struct registry_json_walk_person_urls_callback *c = (struct registry_json_walk_person_urls_callback *)data;
+static int registry_json_person_url_callback(REGISTRY_PERSON_URL *pu, struct registry_json_walk_person_urls_callback *c) {
+ if(unlikely(!asterisks))
+ asterisks = string_strdupz("***");
+
struct web_client *w = c->w;
- if (!strcmp(pu->url->url,"***")) return 0;
+ if (pu->url == asterisks) return 0;
buffer_json_add_array_item_array(w->response.data);
buffer_json_add_array_item_string(w->response.data, pu->machine->guid);
- buffer_json_add_array_item_string(w->response.data, pu->url->url);
+ buffer_json_add_array_item_string(w->response.data, string2str(pu->url));
buffer_json_add_array_item_uint64(w->response.data, pu->last_t * (uint64_t) 1000);
buffer_json_add_array_item_uint64(w->response.data, pu->usages);
- buffer_json_add_array_item_string(w->response.data, pu->machine_name);
+ buffer_json_add_array_item_string(w->response.data, string2str(pu->machine_name));
buffer_json_array_close(w->response.data);
return 1;
}
// callback for rendering MACHINE_URLs
-static int registry_json_machine_url_callback(const DICTIONARY_ITEM *item __maybe_unused, void *entry, void *data) {
- REGISTRY_MACHINE_URL *mu = (REGISTRY_MACHINE_URL *)entry;
- struct registry_json_walk_person_urls_callback *c = (struct registry_json_walk_person_urls_callback *)data;
+static int registry_json_machine_url_callback(REGISTRY_MACHINE_URL *mu, struct registry_json_walk_person_urls_callback *c) {
+ if(unlikely(!asterisks))
+ asterisks = string_strdupz("***");
+
struct web_client *w = c->w;
REGISTRY_MACHINE *m = c->m;
- if (!strcmp(mu->url->url,"***")) return 0;
+ if (mu->url == asterisks) return 0;
buffer_json_add_array_item_array(w->response.data);
buffer_json_add_array_item_string(w->response.data, m->guid);
- buffer_json_add_array_item_string(w->response.data, mu->url->url);
+ buffer_json_add_array_item_string(w->response.data, string2str(mu->url));
buffer_json_add_array_item_uint64(w->response.data, mu->last_t * (uint64_t) 1000);
buffer_json_add_array_item_uint64(w->response.data, mu->usages);
buffer_json_array_close(w->response.data);
@@ -130,9 +138,7 @@ struct registry_person_url_callback_verify_machine_exists_data {
int count;
};
-static inline int registry_person_url_callback_verify_machine_exists(void *entry, void *data) {
- struct registry_person_url_callback_verify_machine_exists_data *d = (struct registry_person_url_callback_verify_machine_exists_data *)data;
- REGISTRY_PERSON_URL *pu = (REGISTRY_PERSON_URL *)entry;
+static inline int registry_person_url_callback_verify_machine_exists(REGISTRY_PERSON_URL *pu, struct registry_person_url_callback_verify_machine_exists_data *d) {
REGISTRY_MACHINE *m = d->m;
if(pu->machine == m)
@@ -161,34 +167,54 @@ int registry_request_hello_json(RRDHOST *host, struct web_client *w) {
buffer_json_member_add_string(w->response.data, "cloud_base_url", registry.cloud_base_url);
buffer_json_member_add_boolean(w->response.data, "anonymous_statistics", netdata_anonymous_statistics_enabled);
+ buffer_json_member_add_array(w->response.data, "nodes");
+ RRDHOST *h;
+ dfe_start_read(rrdhost_root_index, h) {
+ buffer_json_add_array_item_object(w->response.data);
+ buffer_json_member_add_string(w->response.data, "machine_guid", h->machine_guid);
+ buffer_json_member_add_string(w->response.data, "hostname", rrdhost_registry_hostname(h));
+ buffer_json_object_close(w->response.data);
+ }
+ dfe_done(h);
+ buffer_json_array_close(w->response.data);
+
registry_json_footer(w);
return HTTP_RESP_OK;
}
// ----------------------------------------------------------------------------
-//public ACCESS request
-
-#define REGISTRY_VERIFY_COOKIES_GUID "give-me-back-this-cookie-now--please"
+// public ACCESS request
// the main method for registering an access
int registry_request_access_json(RRDHOST *host, struct web_client *w, char *person_guid, char *machine_guid, char *url, char *name, time_t when) {
if(unlikely(!registry.enabled))
return registry_json_disabled(host, w, "access");
+ if(!registry_is_valid_url(url)) {
+ buffer_flush(w->response.data);
+ buffer_strcat(w->response.data, "Invalid URL given in the request");
+ return HTTP_RESP_BAD_REQUEST;
+ }
+
// ------------------------------------------------------------------------
- // verify the browser supports cookies
+ // verify the browser supports cookies or the bearer
if(registry.verify_cookies_redirects > 0 && !person_guid[0]) {
+ registry_request_access(REGISTRY_VERIFY_COOKIES_GUID, machine_guid, url, name, when);
+
buffer_flush(w->response.data);
registry_set_cookie(w, REGISTRY_VERIFY_COOKIES_GUID);
w->response.data->content_type = CT_APPLICATION_JSON;
registry_json_header(host, w, "access", REGISTRY_STATUS_REDIRECT);
+ buffer_json_member_add_string(w->response.data, "person_guid", REGISTRY_VERIFY_COOKIES_GUID);
buffer_json_member_add_string(w->response.data, "registry", registry.registry_to_announce);
registry_json_footer(w);
return HTTP_RESP_OK;
}
- if(unlikely(person_guid[0] && !strcmp(person_guid, REGISTRY_VERIFY_COOKIES_GUID)))
+ if(unlikely(person_guid[0] && is_dummy_person(person_guid)))
+ // it passed the check - they gave us a different person_guid
+ // empty the dummy one, so that we will generate a new person_guid
person_guid[0] = '\0';
// ------------------------------------------------------------------------
@@