Use booleans instead of string for controlling the blocking status. Return the GET response after a successful PATCH request.

Signed-off-by: DL6ER <dl6er@dl6er.de>
This commit is contained in:
DL6ER 2020-06-17 18:43:10 +02:00
parent be3b4045ae
commit fa5f6cdcdf
No known key found for this signature in database
GPG Key ID: 00135ACBD90B28DD
7 changed files with 113 additions and 93 deletions

View File

@ -18,88 +18,109 @@
// set_blockingmode_timer()
#include "../timers.h"
static int get_blocking(struct mg_connection *conn)
{
// Return current status
cJSON *json = JSON_NEW_OBJ();
const bool blocking = get_blockingstatus();
JSON_OBJ_ADD_BOOL(json, "blocking", blocking);
// Get timer information (if applicable)
int delay;
bool target_status;
get_blockingmode_timer(&delay, &target_status);
if(delay > -1)
{
cJSON *timer = JSON_NEW_OBJ();
JSON_OBJ_ADD_NUMBER(timer, "delay", delay);
JSON_OBJ_ADD_BOOL(timer, "blocking_target", target_status);
JSON_OBJ_ADD_ITEM(json, "timer", timer);
}
else
{
JSON_OBJ_ADD_NULL(json, "timer");
}
// Send object (HTTP 200 OK)
JSON_SEND_OBJECT(json);
}
static int set_blocking(struct mg_connection *conn)
{
// Verify requesting client is allowed to access this ressource
if(check_client_auth(conn) < 0)
{
return send_json_unauthorized(conn);
}
char buffer[1024];
const int data_len = mg_read(conn, buffer, sizeof(buffer) - 1);
if ((data_len < 1) || (data_len >= (int)sizeof(buffer))) {
return send_json_error(conn, 400,
"bad_request", "No request body data",
NULL);
}
buffer[data_len] = '\0';
cJSON *obj = cJSON_Parse(buffer);
if (obj == NULL) {
return send_json_error(conn, 400,
"bad_request",
"Invalid request body data",
NULL);
}
cJSON *elem = cJSON_GetObjectItemCaseSensitive(obj, "blocking");
if (!cJSON_IsBool(elem)) {
cJSON_Delete(obj);
return send_json_error(conn, 400,
"bad_request",
"No \"blocking\" boolean in body data",
NULL);
}
const bool target_status = cJSON_IsTrue(elem);
// Get (optional) delay
int delay = -1;
elem = cJSON_GetObjectItemCaseSensitive(obj, "delay");
if (cJSON_IsNumber(elem) && elem->valuedouble > 0.0)
delay = elem->valueint;
// Free memory not needed any longer
cJSON_Delete(obj);
if(target_status == get_blockingstatus())
{
// The blocking status does not need to be changed
// If delay is absent (or -1), we delete a possibly running timer
if(delay < 0)
set_blockingmode_timer(-1, true);
}
else
{
// Activate requested status
set_blockingstatus(target_status);
// Start timer (-1 disables all running timers)
set_blockingmode_timer(delay, !target_status);
}
// Return GET property as result of POST/PUT/PATCH action
// if no error happened above
return get_blocking(conn);
}
int api_dns_blockingstatus(struct mg_connection *conn)
{
int method = http_method(conn);
if(method == HTTP_GET)
{
// Return current status
cJSON *json = JSON_NEW_OBJ();
const char *action = get_blockingstatus() ? "active" : "inactive";
JSON_OBJ_REF_STR(json, "status", action);
JSON_SEND_OBJECT(json);
return get_blocking(conn);
}
else if(method == HTTP_POST)
else if(method == HTTP_PATCH)
{
// Verify requesting client is allowed to access this ressource
if(check_client_auth(conn) < 0)
{
return send_json_unauthorized(conn);
}
char buffer[1024];
int data_len = mg_read(conn, buffer, sizeof(buffer) - 1);
if ((data_len < 1) || (data_len >= (int)sizeof(buffer))) {
return send_json_error(conn, 400,
"bad_request", "No request body data",
NULL);
}
buffer[data_len] = '\0';
cJSON *obj = cJSON_Parse(buffer);
if (obj == NULL) {
return send_json_error(conn, 400,
"bad_request",
"Invalid request body data",
NULL);
}
cJSON *elem1 = cJSON_GetObjectItemCaseSensitive(obj, "status");
if (!cJSON_IsString(elem1)) {
cJSON_Delete(obj);
return send_json_error(conn, 400,
"bad_request",
"No \"status\" string in body data",
NULL);
}
char *status = strdup(elem1->valuestring);
unsigned int delay = -1;
cJSON *elem2 = cJSON_GetObjectItemCaseSensitive(obj, "delay");
if (cJSON_IsNumber(elem2) && elem2->valuedouble > 0.0)
{
delay = elem2->valueint;
}
cJSON_Delete(obj);
cJSON *json = JSON_NEW_OBJ();
JSON_OBJ_COPY_STR(json, "status", status);
// Execute requested status
if(strcmp(status, "active") == 0)
{
// If no "time" key was present, we call this subroutine with
// delay == -1 which will disable all previously set timers
set_blockingmode_timer(delay, false);
set_blockingstatus(true);
}
else if(strcmp(status, "inactive") == 0)
{
// If no "time" key was present, we call this subroutine with
// delay == -1 which will disable all previously set timers
set_blockingmode_timer(delay, true);
set_blockingstatus(false);
}
else
{
free(status);
return send_json_error(conn, 400,
"bad_request",
"Invalid \"status\" requested",
json);
}
free(status);
JSON_SEND_OBJECT(json);
return set_blocking(conn);
}
else
{

View File

@ -50,12 +50,18 @@ void sleepms(const int milliseconds)
}
static int timer_delay = -1;
static bool timer_targer_state;
static bool timer_target_status;
void set_blockingmode_timer(int delay, bool blocked)
void set_blockingmode_timer(int delay, bool target_status)
{
timer_delay = delay;
timer_targer_state = blocked;
timer_target_status = target_status;
}
void get_blockingmode_timer(int *delay, bool *target_status)
{
*delay = timer_delay;
*target_status = timer_target_status;
}
void *timer(void *val)
@ -74,7 +80,7 @@ void *timer(void *val)
}
else if(timer_delay == 0)
{
set_blockingstatus(timer_targer_state);
set_blockingstatus(timer_target_status);
timer_delay = -1;
}
sleepms(1000);

View File

@ -19,6 +19,7 @@ void timer_start(const int i);
double timer_elapsed_msec(const int i);
void sleepms(const int milliseconds);
void set_blockingmode_timer(int delay, bool blocked);
void get_blockingmode_timer(int *delay, bool *target_status);
void *timer(void *val);
#endif //TIMERS_H

View File

@ -175,23 +175,15 @@ int http_method(struct mg_connection *conn)
{
const struct mg_request_info *request = mg_get_request_info(conn);
if(strcmp(request->request_method, "GET") == 0)
{
return HTTP_GET;
}
else if(strcmp(request->request_method, "DELETE") == 0)
{
return HTTP_DELETE;
}
else if(strcmp(request->request_method, "PUT") == 0)
{
return HTTP_PUT;
}
else if(strcmp(request->request_method, "POST") == 0)
{
return HTTP_POST;
}
else if(strcmp(request->request_method, "PATCH") == 0)
return HTTP_PATCH;
else
{
return HTTP_UNKNOWN;
}
}

View File

@ -45,7 +45,7 @@ int get_int_var(const char *source, const char *var);
#define GET_VAR(variable, destination, source) mg_get_var(source, strlen(source), variable, destination, sizeof(destination))
// Method routines
enum { HTTP_UNKNOWN, HTTP_GET, HTTP_POST, HTTP_PUT, HTTP_DELETE };
enum { HTTP_UNKNOWN, HTTP_GET, HTTP_POST, HTTP_PUT, HTTP_PATCH, HTTP_DELETE };
int http_method(struct mg_connection *conn);
// Utils

View File

@ -80,7 +80,7 @@
}
#define JSON_OBJ_ADD_BOOL(object, key, value) {\
cJSON *bool_item = cJSON_CreateBool(value ? cJSON_True : cJSON_False); \
cJSON *bool_item = cJSON_CreateBool((cJSON_bool)value); \
if(bool_item == NULL) \
{ \
cJSON_Delete(object); \

View File

@ -60,9 +60,9 @@ int ph7_handler(struct mg_connection *conn, void *cbdata)
}
char full_path[buffer_len];
strncpy(full_path, httpsettings.webroot, webroot_len);
memcpy(full_path, httpsettings.webroot, webroot_len);
full_path[webroot_len] = '/';
strncpy(full_path + webroot_len + 1u, local_uri, local_uri_len);
memcpy(full_path + webroot_len + 1u, local_uri, local_uri_len);
full_path[webroot_len + local_uri_len + 1u] = '\0';
if(append_index)
{