Skip to content

Commit

Permalink
[agroal#392] Add application name and version in management protocol
Browse files Browse the repository at this point in the history
In order to improve debugging, [agroal#392] suggested to write
the sender application name and its version into the header
over which pgagroal-cli and pgagroal communicate.

Introduces the 'write_header_info' function in
management.c.
  • Loading branch information
EuGig committed Apr 3, 2024
1 parent 5dcfb89 commit cfe5b67
Showing 1 changed file with 155 additions and 7 deletions.
162 changes: 155 additions & 7 deletions src/libpgagroal/management.c
Original file line number Diff line number Diff line change
Expand Up @@ -53,12 +53,18 @@
#include <openssl/ssl.h>

#define MANAGEMENT_HEADER_SIZE 5
#define MANAGEMENT_INFO_SIZE sizeof(struct info)

#define pgagroal 1
#define pgagroal_cli 2
#define pgagroal_vualt 3

static int read_complete(SSL* ssl, int socket, void* buf, size_t size);
static int write_complete(SSL* ssl, int socket, void* buf, size_t size);
static int write_socket(int socket, void* buf, size_t size);
static int write_ssl(SSL* ssl, void* buf, size_t size);
static int write_header(SSL* ssl, int fd, signed char type, int slot);
static int write_info(char* buffer, int command, int offset);

static int pgagroal_management_write_conf_ls_detail(int socket, char* what);
static int pgagroal_management_read_conf_ls_detail(SSL* ssl, int socket, char* buffer);
Expand All @@ -71,10 +77,26 @@ static cJSON* pgagroal_managment_json_read_config_get(int socket, char* config_k
static cJSON* pgagroal_management_json_read_conf_ls(SSL* ssl, int socket);
static int pgagroal_management_json_print_conf_ls(cJSON* json);

static int get_version_number(char* version);
static char* get_command_string(int command);

/*
* stores the application name and its version
* which are sent through the socket
*/
struct info
{
char* s;
int command;
char* v;
int version;
};

int
pgagroal_management_read_header(int socket, signed char* id, int32_t* slot)
{
char header[MANAGEMENT_HEADER_SIZE];
char buf_info[MANAGEMENT_INFO_SIZE];

if (read_complete(NULL, socket, &header[0], sizeof(header)))
{
Expand All @@ -86,6 +108,13 @@ pgagroal_management_read_header(int socket, signed char* id, int32_t* slot)
*id = pgagroal_read_byte(&(header));
*slot = pgagroal_read_int32(&(header[1]));

if (read_complete(NULL, socket, &buf_info[0], sizeof(buf_info)))
{
pgagroal_log_warn("pgagroal_management_read_header: %d %s", socket, strerror(errno));
errno = 0;
goto error;
}

return 0;

error:
Expand Down Expand Up @@ -188,7 +217,6 @@ pgagroal_management_read_payload(int socket, signed char id, int* payload_i, cha
case MANAGEMENT_CONFIG_GET:
case MANAGEMENT_GET_PASSWORD:
case MANAGEMENT_CONFIG_SET:

if (read_complete(NULL, socket, &buf4[0], sizeof(buf4)))
{
goto error;
Expand Down Expand Up @@ -685,11 +713,15 @@ pgagroal_management_json_read_status_details(SSL* ssl, int socket, bool include_
int limits = 0;
int servers = 0;
char header[12 + MAX_NUMBER_OF_CONNECTIONS];
char buf_info[MANAGEMENT_INFO_SIZE];

memset(&buf, 0, sizeof(buf));
memset(&disabled, 0, sizeof(disabled));
memset(&header, 0, sizeof(header));

// consumes info
read_complete(ssl, socket, &buf_info[0], sizeof(buf_info));

cJSON* json = pgagroal_json_create_new_command_object(include_details ? "status details" : "status", true, "pgagroal-cli");
cJSON* output = pgagroal_json_extract_command_output_object(json);

Expand Down Expand Up @@ -900,10 +932,21 @@ int
pgagroal_management_write_status(int socket, bool graceful)
{
char buf[16];
char buf_info[MANAGEMENT_INFO_SIZE];

int active;
int total;
struct main_configuration* config;

write_info(buf_info, pgagroal, 0);

if (write_complete(NULL, socket, &buf_info, sizeof(buf_info)))
{
pgagroal_log_warn("pgagroal_management_write_status: write: %d %s", socket, strerror(errno));
errno = 0;
goto error;
}

memset(&buf, 0, sizeof(buf));
active = 0;
total = 0;
Expand Down Expand Up @@ -1014,8 +1057,9 @@ pgagroal_management_read_details(SSL* ssl, int socket, char output_format)
int
pgagroal_management_write_details(int socket)
{
char header[12 + MAX_NUMBER_OF_CONNECTIONS];
struct main_configuration* config;
int offset = 12;
char header[offset + MAX_NUMBER_OF_CONNECTIONS];

config = (struct main_configuration*)shmem;

Expand All @@ -1028,7 +1072,7 @@ pgagroal_management_write_details(int socket)
for (int i = 0; i < config->max_connections; i++)
{
signed char state = atomic_load(&config->states[i]);
header[12 + i] = (char)state;
header[offset + i] = (char)state;
}

if (write_complete(NULL, socket, header, sizeof(header)))
Expand Down Expand Up @@ -1128,7 +1172,7 @@ pgagroal_management_isalive(SSL* ssl, int fd)
int
pgagroal_management_read_isalive(SSL* ssl, int socket, int* status, char output_format)
{
char buf[4];
char buf[MANAGEMENT_INFO_SIZE + 4];

memset(&buf, 0, sizeof(buf));

Expand All @@ -1139,7 +1183,7 @@ pgagroal_management_read_isalive(SSL* ssl, int socket, int* status, char output_
goto error;
}

*status = pgagroal_read_int32(&buf);
*status = pgagroal_read_int32(&buf[MANAGEMENT_INFO_SIZE]);

// do I need to provide JSON output?
if (output_format == COMMAND_OUTPUT_FORMAT_JSON)
Expand Down Expand Up @@ -1177,6 +1221,16 @@ int
pgagroal_management_write_isalive(int socket, bool gracefully)
{
char buf[4];
char buf_info[MANAGEMENT_INFO_SIZE];

write_info(buf_info, pgagroal, 0);

if (write_complete(NULL, socket, &buf_info, sizeof(buf_info)))
{
pgagroal_log_warn("pgagroal_management_write_isalive: write: %d %s", socket, strerror(errno));
errno = 0;
goto error;
}

memset(&buf, 0, sizeof(buf));

Expand Down Expand Up @@ -1696,15 +1750,84 @@ write_ssl(SSL* ssl, void* buf, size_t size)
return 1;
}

/**
* Function to write sender application name and its version
* into header socket.
*
* @param header: the header to write sender application name and its version into
* @param command: the server application name
* @param offset: the offset at which info has to be written
* @return 0 on success
*/
static int
write_info(char* buffer, int command, int offset)
{
struct info info;

info.command = command;
info.version = get_version_number(PGAGROAL_VERSION);
info.s = "S:";
info.v = ",V:";

pgagroal_write_string(buffer + offset, info.s);
pgagroal_write_int32(buffer + offset + 2, info.command);
pgagroal_write_string(buffer + offset + 6, info.v);
pgagroal_write_int32(buffer + offset + 9, info.version);

char* str_command = get_command_string(command);

pgagroal_log_debug("Info: %s%s%s%d", info.s, str_command, info.v, info.version);

return 0;
}

/*
* Utility function to convert PGAGROAL_VERSION into a number.
*/
static int
get_version_number(char* version)
{
int major = 0;
int minor = 0;
int patch = 0;
sscanf(version, "%d.%d.%d", &major, &minor, &patch);

int version_number = major * 100000 + minor * 1000 + 10 * patch;

return version_number;
}

/*
* Utility function to convert command into a string.
*/
static char*
get_command_string(int command)
{
switch (command)
{
case 1:
return "pgagroal";
case 2:
return "pgagroal-cli";
case 3:
return "pgagroal-vault";
default:
pgagroal_log_debug("get_command_string got unexpected value: %d\n", command);
return "unexpected";
}
}

static int
write_header(SSL* ssl, int fd, signed char type, int slot)
{
char header[MANAGEMENT_HEADER_SIZE];
char header[MANAGEMENT_HEADER_SIZE + MANAGEMENT_INFO_SIZE];

pgagroal_write_byte(&(header), type);
pgagroal_write_int32(&(header[1]), slot);

return write_complete(ssl, fd, &(header), MANAGEMENT_HEADER_SIZE);
write_info(header, pgagroal_cli, MANAGEMENT_HEADER_SIZE);

return write_complete(ssl, fd, &(header), sizeof(header));
}

int
Expand Down Expand Up @@ -1768,8 +1891,17 @@ pgagroal_management_write_config_get(int socket, char* config_key)
{
char data[MISC_LENGTH];
char buf[4];
char buf_info[MANAGEMENT_INFO_SIZE];

size_t size;

write_info(buf_info, pgagroal, 0);
if (write_complete(NULL, socket, buf_info, sizeof(buf_info)))
{
pgagroal_log_debug("pgagroal_management_config_get: write: %d %s", socket, strerror(errno));
goto error;
}

if (!config_key || !strlen(config_key))
{
pgagroal_log_debug("pgagroal_management_write_config_get: no key specified");
Expand Down Expand Up @@ -1884,6 +2016,8 @@ pgagroal_managment_json_read_config_get(int socket, char* config_key, char* expe
int
pgagroal_management_read_config_get(int socket, char* config_key, char* expected_value, bool verbose, char output_format)
{
char buf_info[MANAGEMENT_INFO_SIZE];
read_complete(NULL, socket, &buf_info[0], sizeof(buf_info));

cJSON* json = pgagroal_managment_json_read_config_get(socket, config_key, expected_value);
int status = EXIT_STATUS_OK;
Expand Down Expand Up @@ -2103,6 +2237,14 @@ pgagroal_management_write_conf_ls(int socket)

config = (struct main_configuration*)shmem;

char buf_info[MANAGEMENT_INFO_SIZE];
write_info(buf_info, pgagroal, 0);

if (write_complete(NULL, socket, &buf_info, sizeof(buf_info)))
{
goto error;
}

if (pgagroal_management_write_conf_ls_detail(socket, config->common.configuration_path))
{
goto error;
Expand Down Expand Up @@ -2429,6 +2571,7 @@ pgagroal_management_json_read_conf_ls(SSL* ssl, int socket)
{
char buf[4];
char* buffer;
char buf_info[MANAGEMENT_INFO_SIZE];

cJSON* json = pgagroal_json_create_new_command_object("conf ls", true, "pgagroal-cli");
cJSON* output = pgagroal_json_extract_command_output_object(json);
Expand All @@ -2442,6 +2585,11 @@ pgagroal_management_json_read_conf_ls(SSL* ssl, int socket)
memset(&buf, 0, sizeof(buf));
buffer = calloc(1, MAX_PATH);

if (read_complete(ssl, socket, &buf_info[0], sizeof(buf_info)))
{
goto error;
}

if (pgagroal_management_read_conf_ls_detail(ssl, socket, buffer))
{
goto error;
Expand Down

0 comments on commit cfe5b67

Please sign in to comment.