json: refactor std::vector to list_head

Signed-off-by: Nicolás A. Ortega Froysa <nicolas.ortega@zevenet.com>
This commit is contained in:
Nicolás A. Ortega Froysa 2023-05-29 14:45:03 +02:00
parent d2ba5edb99
commit 0fb826fb76
3 changed files with 104 additions and 52 deletions

View File

@ -18,11 +18,10 @@
#ifndef _ZPROXY_JSON_H_
#define _ZPROXY_JSON_H_
#include <cstdio>
#include <jansson.h>
#include <stdarg.h>
#include <vector>
#include "config.h"
#include "list.h"
#include "session.h"
#include "state.h"
#include "monitor.h"
@ -77,23 +76,28 @@ int zproxy_json_decode_session(const char *buf, char *sess_id, size_t sess_id_le
time_t *last_seen);
struct json_session {
std::string id;
std::string backend_id;
struct list_head list;
char id[MAX_SESSION_ID];
char backend_id[CONFIG_IDENT_MAX];
time_t last_seen;
};
struct json_sess_service {
struct list_head list;
char name[CONFIG_IDENT_MAX];
std::vector<struct json_session> sessions;
struct list_head sessions;
};
struct json_sess_listener {
struct list_head list;
uint32_t id;
std::vector<struct json_sess_service> services;
struct list_head services;
};
int zproxy_json_decode_glob_sessions(const char *buf,
std::vector<struct json_sess_listener> &listeners);
struct list_head *listeners);
int zproxy_json_decode_sessions(const char *buf,
std::vector<struct json_session> &sessions);
struct list_head *sessions);
void zproxy_json_sess_sessions_free(struct list_head *sessions);
void zproxy_json_sess_listener_free(struct list_head *listeners);
int zproxy_json_decode_backend(const char *buf, char *id, size_t id_len,
char *address, size_t address_len, int *port,
int *https, int *weight, int *priority,

View File

@ -16,6 +16,7 @@
*/
#include "config.h"
#include "list.h"
#include "monitor.h"
#include "session.h"
#include "state.h"
@ -312,8 +313,9 @@ static enum ws_responses handle_patch(const std::string &req_path,
req_path.c_str(), matches)) {
GET_MATCH_2PARAM(req_path, param1, service_id);
const int listener_id = atoi(param1.c_str());
std::vector<struct json_session> new_sessions;
if (zproxy_json_decode_sessions(req_msg, new_sessions) < 0) {
struct list_head new_sessions;
struct json_session *session;
if (zproxy_json_decode_sessions(req_msg, &new_sessions) < 0) {
*resp_buf = zproxy_json_return_err("Failed to decode JSON.");
return WS_HTTP_400;
}
@ -336,24 +338,25 @@ static enum ws_responses handle_patch(const std::string &req_path,
}
zproxy_sessions_flush(sessions);
for (struct json_session &i : new_sessions) {
list_for_each_entry(session, &new_sessions, list) {
struct zproxy_backend_cfg *backend =
find_backend(cfg, listener_id, service_id.c_str(),
i.backend_id.c_str());
session->backend_id);
if (!backend) {
*resp_buf = zproxy_json_return_err("Backend %s doesn't exist.",
i.backend_id.c_str());
session->backend_id);
return WS_HTTP_500;
}
zproxy_session_node *sess =
zproxy_session_add(sessions, i.id.data(), &backend->runtime.addr);
zproxy_session_add(sessions, session->id, &backend->runtime.addr);
if (!sess) {
*resp_buf = zproxy_json_return_err("Failed to create session");
return WS_HTTP_500;
}
sess->timestamp = i.last_seen;
sess->timestamp = session->last_seen;
zproxy_session_free(&sess);
}
zproxy_json_sess_sessions_free(&new_sessions);
zproxy_state_release(&state);
} else if (zproxy_regex_exec(API_REGEX_SELECT_BACKEND_STATUS,
@ -440,51 +443,57 @@ static enum ws_responses handle_patch(const std::string &req_path,
} else if (zproxy_regex_exec(API_REGEX_SELECT_SESSIONS,
req_path.c_str(), matches)) {
struct zproxy_http_state *state;
std::vector<struct json_sess_listener> sess_listeners;
if (zproxy_json_decode_glob_sessions(req_msg, sess_listeners) < 0) {
struct list_head sess_listeners;
const struct json_sess_listener *sess_listener;
const struct json_sess_service *sess_service;
const struct json_session *session;
if (zproxy_json_decode_glob_sessions(req_msg, &sess_listeners) < 0) {
*resp_buf = zproxy_json_return_err("Failed to decode JSON.");
return WS_HTTP_500;
}
for (auto &i : sess_listeners) {
state = zproxy_state_lookup(i.id);
list_for_each_entry(sess_listener, &sess_listeners, list) {
state = zproxy_state_lookup(sess_listener->id);
if (!state) {
*resp_buf = zproxy_json_return_err("Listener %d doesn't exist.",
i.id);
sess_listener->id);
return WS_HTTP_500;
}
for (auto &j : i.services) {
list_for_each_entry(sess_service, &sess_listener->services, list) {
struct zproxy_sessions *sessions;
sessions = zproxy_state_get_service_sessions(j.name, &state->services);
sessions = zproxy_state_get_service_sessions(sess_service->name, &state->services);
if (!sessions) {
*resp_buf = zproxy_json_return_err("Service %s doesn't exist.",
j.name);
sess_service->name);
return WS_HTTP_500;
}
zproxy_sessions_flush(sessions);
for (auto &k : j.sessions) {
list_for_each_entry(session, &sess_service->sessions, list) {
struct zproxy_backend_cfg *backend =
find_backend(cfg, i.id, j.name,
k.backend_id.c_str());
find_backend(cfg, sess_listener->id,
sess_service->name,
session->backend_id);
if (!backend) {
*resp_buf = zproxy_json_return_err("Backend %s doesn't exist.",
k.backend_id.c_str());
session->backend_id);
return WS_HTTP_500;
}
zproxy_session_node *sess =
zproxy_session_add(sessions,
k.id.data(),
session->id,
&backend->runtime.addr);
if (!sess) {
*resp_buf = zproxy_json_return_err("Failed to create session");
return WS_HTTP_500;
}
sess->timestamp = k.last_seen;
sess->timestamp = session->last_seen;
zproxy_session_free(&sess);
}
}
zproxy_state_release(&state);
}
zproxy_json_sess_listener_free(&sess_listeners);
} else {
return WS_HTTP_400;
}

View File

@ -15,8 +15,6 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <cstdio>
#include <cstring>
#include <jansson.h>
#include <netdb.h>
#include <pthread.h>
@ -514,7 +512,7 @@ int zproxy_json_decode_session(const char *buf, char *sess_id, size_t sess_id_le
}
int zproxy_json_decode_glob_sessions(const char *buf,
std::vector<struct json_sess_listener> &listeners)
struct list_head *listeners)
{
json_error_t json_err;
json_t *listener_arr, *listener_obj, *service_arr, *service_obj,
@ -529,39 +527,50 @@ int zproxy_json_decode_glob_sessions(const char *buf,
return -1;
}
INIT_LIST_HEAD(listeners);
json_array_foreach(listener_arr, i, listener_obj) {
struct json_sess_listener listener;
struct json_sess_listener *listener =
(struct json_sess_listener*)calloc(1, sizeof(struct json_sess_listener));
req_var = json_object_get(listener_obj, "id");
listener.id = json_integer_value(req_var);
listener->id = json_integer_value(req_var);
INIT_LIST_HEAD(&listener->services);
service_arr = json_object_get(listener_obj, "services");
json_array_foreach(service_arr, j, service_obj) {
struct json_sess_service service;
struct json_sess_service *service =
(struct json_sess_service*)calloc(1, sizeof(struct json_sess_service));
req_var = json_object_get(service_obj, "name");
snprintf(service.name, CONFIG_IDENT_MAX,
snprintf(service->name, CONFIG_IDENT_MAX,
json_string_value(req_var), "%s");
INIT_LIST_HEAD(&service->sessions);
session_arr = json_object_get(service_obj, "sessions");
json_array_foreach(session_arr, k, session_obj) {
struct json_session session;
if ((req_var = json_object_get(session_obj, "id")))
session.id = json_string_value(req_var);
struct json_session *session =
(struct json_session*)calloc(1, sizeof(struct json_session));
if ((req_var = json_object_get(session_obj, "id"))) {
snprintf(session->id, MAX_SESSION_ID,
"%s", json_string_value(req_var));
}
if ((req_var = json_object_get(session_obj, "backend-id")))
session.backend_id = json_string_value(req_var);
if ((req_var = json_object_get(session_obj, "backend-id"))) {
snprintf(session->backend_id,
CONFIG_IDENT_MAX, "%s",
json_string_value(req_var));
}
if ((req_var = json_object_get(session_obj, "last-seen")))
session.last_seen = (time_t)json_integer_value(req_var);
session->last_seen = (time_t)json_integer_value(req_var);
else
session.last_seen = -1;
session->last_seen = -1;
service.sessions.push_back(session);
list_add_tail(&session->list, &service->sessions);
}
listener.services.push_back(service);
list_add_tail(&service->list, &listener->services);
}
listeners.push_back(listener);
list_add_tail(&listener->list, listeners);
}
json_decref(listener_arr);
@ -570,7 +579,7 @@ int zproxy_json_decode_glob_sessions(const char *buf,
}
int zproxy_json_decode_sessions(const char *buf,
std::vector<struct json_session> &sessions)
struct list_head *sessions)
{
json_error_t json_err;
json_t *sess_array, *sess;
@ -589,18 +598,48 @@ int zproxy_json_decode_sessions(const char *buf,
return -1;
}
INIT_LIST_HEAD(sessions);
json_array_foreach(sess_array, sess_i, sess) {
sessions.push_back({
json_string_value(json_object_get(sess, "id")),
json_string_value(json_object_get(sess, "backend-id")),
json_integer_value(json_object_get(sess, "last-seen")),
});
struct json_session *session =
(struct json_session*)calloc(1, sizeof(struct json_session));
snprintf(session->id, MAX_SESSION_ID, "%s",
json_string_value(json_object_get(sess, "id")));
snprintf(session->backend_id, MAX_SESSION_ID, "%s",
json_string_value(json_object_get(sess, "backend-id")));
session->last_seen = json_integer_value(json_object_get(sess, "last-seen"));
list_add_tail(&session->list, sessions);
}
json_decref(sess_array);
return 1;
}
void zproxy_json_sess_sessions_free(struct list_head *sessions)
{
struct json_session *session, *sess_next;
list_for_each_entry_safe(session, sess_next, sessions, list) {
list_del(&session->list);
free(session);
}
}
void zproxy_json_sess_listener_free(struct list_head *listeners)
{
struct json_sess_listener *listener, *list_next;
struct json_sess_service *service, *serv_next;
list_for_each_entry_safe(listener, list_next, listeners, list) {
list_for_each_entry_safe(service, serv_next, &listener->services, list) {
zproxy_json_sess_sessions_free(&service->sessions);
list_del(&service->list);
free(service);
}
list_del(&listener->list);
free(listener);
}
}
int zproxy_json_decode_backend(const char *buf, char *id, size_t id_len,
char *address, size_t address_len, int *port,
int *https, int *weight, int *priority,