aboutsummaryrefslogtreecommitdiff
path: root/src/ping903.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/ping903.c')
-rw-r--r--src/ping903.c276
1 files changed, 206 insertions, 70 deletions
diff --git a/src/ping903.c b/src/ping903.c
index efc6246..47456a7 100644
--- a/src/ping903.c
+++ b/src/ping903.c
@@ -165,11 +165,10 @@ http_log(struct MHD_Connection *connection,
user_agent ? user_agent : "");
free(ipstr);
}
-
static int
-http_error(struct MHD_Connection *conn,
- char const *method, char const *url, int status)
+http_response(struct MHD_Connection *conn,
+ char const *method, char const *url, int status)
{
int ret;
struct MHD_Response *resp =
@@ -233,6 +232,7 @@ json_to_str(struct json_value *obj)
static int
httpd_json_response(struct MHD_Connection *conn,
char const *url, char const *method,
+ int status,
struct json_value *val)
{
char *reply;
@@ -242,24 +242,25 @@ httpd_json_response(struct MHD_Connection *conn,
reply = json_to_str(val);
json_value_free(val);
if (!reply)
- return http_error(conn, method, url,
+ return http_response(conn, method, url,
MHD_HTTP_INTERNAL_SERVER_ERROR);
resp = MHD_create_response_from_buffer(strlen(reply),
reply, MHD_RESPMEM_MUST_COPY);
- http_log(conn, method, url, MHD_HTTP_OK, reply);
+ http_log(conn, method, url, status, reply);
free(reply);
MHD_add_response_header(resp,
MHD_HTTP_HEADER_CONTENT_TYPE,
"application/json");
- ret = MHD_queue_response(conn, MHD_HTTP_OK, resp);
+ ret = MHD_queue_response(conn, status, resp);
MHD_destroy_response(resp);
return ret;
}
static int
ept_config(struct MHD_Connection *conn,
- const char *url, const char *method, const char *suffix)
+ const char *url, const char *method, const char *suffix,
+ struct json_value *unused)
{
struct json_value *val;
@@ -268,7 +269,7 @@ ept_config(struct MHD_Connection *conn,
val = config_to_json();
if (!val)
- return http_error(conn, method, url,
+ return http_response(conn, method, url,
MHD_HTTP_INTERNAL_SERVER_ERROR);
if (*suffix) {
@@ -276,7 +277,7 @@ ept_config(struct MHD_Connection *conn,
int ret;
if (json_object_get(val, suffix, &jv)) {
- ret = http_error(conn, method, url,
+ ret = http_response(conn, method, url,
(errno == ENOENT)
? MHD_HTTP_NOT_FOUND
: MHD_HTTP_INTERNAL_SERVER_ERROR);
@@ -285,7 +286,7 @@ ept_config(struct MHD_Connection *conn,
}
if (json_value_copy(jv, &cp)) {
- ret = http_error(conn, method, url,
+ ret = http_response(conn, method, url,
MHD_HTTP_INTERNAL_SERVER_ERROR);
json_value_free(val);
return ret;
@@ -294,58 +295,86 @@ ept_config(struct MHD_Connection *conn,
val = cp;
}
- return httpd_json_response(conn, url, method, val);
+ return httpd_json_response(conn, url, method, MHD_HTTP_OK, val);
}
static int
ept_ip_delete(struct MHD_Connection *conn,
- const char *url, const char *method, const char *suffix)
+ const char *url, const char *method, const char *suffix,
+ struct json_value *unused)
{
int ret;
- struct MHD_Response *resp;
-
+
while (*suffix == '/')
suffix++;
if (!*suffix)
- return http_error(conn, method, url, MHD_HTTP_FORBIDDEN);
- if (hostping_delete_by_name(suffix))
- return http_error(conn, method, url, MHD_HTTP_NOT_FOUND);
-
- resp = MHD_create_response_from_buffer(0,
- NULL,
- MHD_RESPMEM_PERSISTENT);
- http_log(conn, method, url, MHD_HTTP_OK, NULL);
- ret = MHD_queue_response(conn, MHD_HTTP_OK, resp);
- MHD_destroy_response(resp);
- return ret;
+ return http_response(conn, method, url, MHD_HTTP_FORBIDDEN);
+ if (pinger_host_delete_by_name(suffix))
+ return http_response(conn, method, url, MHD_HTTP_NOT_FOUND);
+ return http_response(conn, method, url, MHD_HTTP_OK);
}
static int
ept_ip_put(struct MHD_Connection *conn,
- const char *url, const char *method, const char *suffix)
+ const char *url, const char *method, const char *suffix,
+ struct json_value *unused)
{
int ret;
- struct MHD_Response *resp;
while (*suffix == '/')
suffix++;
if (!*suffix)
- return http_error(conn, method, url, MHD_HTTP_FORBIDDEN);
- if (hostping_add_name(suffix))
+ return http_response(conn, method, url, MHD_HTTP_FORBIDDEN);
+ if (pinger_host_add_name(suffix))
//FIXME
- return http_error(conn, method, url, MHD_HTTP_FORBIDDEN);
- resp = MHD_create_response_from_buffer(0,
- NULL,
- MHD_RESPMEM_PERSISTENT);
- http_log(conn, method, url, MHD_HTTP_CREATED, NULL);
- ret = MHD_queue_response(conn, MHD_HTTP_CREATED, resp);
- MHD_destroy_response(resp);
- return ret;
+ return http_response(conn, method, url, MHD_HTTP_FORBIDDEN);
+ return http_response(conn, method, url, MHD_HTTP_CREATED);
+}
+
+static int
+ept_ip_post(struct MHD_Connection *conn,
+ const char *url, const char *method, const char *suffix,
+ struct json_value *obj)
+{
+ char const *err_text;
+ int err_pos;
+ int status;
+
+ status = pinger_hostlist_set(obj, &err_text, &err_pos);
+ if (!err_text && !err_pos)
+ return http_response(conn, method, url, status);
+ else {
+ struct json_value *jv, *err = json_new_object();
+ char *str;
+ int rc;
+
+ if (!err)
+ goto err;
+ if ((jv = json_new_string(err_text)) == NULL)
+ goto err;
+ if (json_object_set(err, "message", jv))
+ goto err;
+ if (err_pos) {
+ if ((jv = json_new_number(err_pos)) == NULL)
+ goto err;
+ if (json_object_set(err, "index", jv))
+ goto err;
+ }
+ str = json_to_str(err);
+ rc = httpd_json_response(conn, url, method, status, err);
+ json_value_free(err);
+ return rc;
+ err:
+ json_value_free(err);
+ return http_response(conn, method, url,
+ MHD_HTTP_INTERNAL_SERVER_ERROR);
+ }
}
static int
ept_host_stat(struct MHD_Connection *conn,
- const char *url, const char *method, const char *suffix)
+ const char *url, const char *method, const char *suffix,
+ struct json_value *unused)
{
struct json_value *val;
int rc;
@@ -359,15 +388,16 @@ ept_host_stat(struct MHD_Connection *conn,
rc = get_hostname_stat(suffix, &val);
}
if (rc)
- return http_error(conn, method, url,
+ return http_response(conn, method, url,
MHD_HTTP_INTERNAL_SERVER_ERROR);
- return httpd_json_response(conn, url, method, val);
+ return httpd_json_response(conn, url, method, MHD_HTTP_OK, val);
}
static int
ept_ip_stat(struct MHD_Connection *conn,
- const char *url, const char *method, const char *suffix)
+ const char *url, const char *method, const char *suffix,
+ struct json_value *unused)
{
struct json_value *val;
int rc;
@@ -376,7 +406,7 @@ ept_ip_stat(struct MHD_Connection *conn,
suffix++;
if (suffix[0] == 0) {
- return http_error(conn, method, url, MHD_HTTP_FORBIDDEN);
+ return http_response(conn, method, url, MHD_HTTP_FORBIDDEN);
} else {
int ret;
struct addrinfo hints, *res;
@@ -385,16 +415,17 @@ ept_ip_stat(struct MHD_Connection *conn,
hints.ai_protocol = IPPROTO_TCP;
rc = getaddrinfo(suffix, NULL, &hints, &res);
if (rc)
- return http_error(conn, method, url,
+ return http_response(conn, method, url,
MHD_HTTP_NOT_FOUND);
rc = get_ipaddr_stat(res->ai_addr, res->ai_addrlen, &val);
if (rc)
- ret = http_error(conn, method, url,
+ ret = http_response(conn, method, url,
MHD_HTTP_INTERNAL_SERVER_ERROR);
else if (val)
- ret = httpd_json_response(conn, url, method, val);
+ ret = httpd_json_response(conn, url, method,
+ MHD_HTTP_OK, val);
else
- ret = http_error(conn, method, url, MHD_HTTP_FORBIDDEN);
+ ret = http_response(conn, method, url, MHD_HTTP_FORBIDDEN);
freeaddrinfo(res);
return ret;
}
@@ -402,7 +433,8 @@ ept_ip_stat(struct MHD_Connection *conn,
static int
ept_ip_match(struct MHD_Connection *conn,
- const char *url, const char *method, const char *suffix)
+ const char *url, const char *method, const char *suffix,
+ struct json_value *unused)
{
struct json_value *val;
int rc;
@@ -413,27 +445,28 @@ ept_ip_match(struct MHD_Connection *conn,
suffix++;
if (suffix[0] == 0)
- return http_error(conn, method, url, MHD_HTTP_FORBIDDEN);
+ return http_response(conn, method, url, MHD_HTTP_FORBIDDEN);
memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_INET;
hints.ai_protocol = IPPROTO_TCP;
rc = getaddrinfo(suffix, NULL, &hints, &res);
if (rc)
- return http_error(conn, method, url, MHD_HTTP_NOT_FOUND);
+ return http_response(conn, method, url, MHD_HTTP_NOT_FOUND);
rc = get_host_matches(&res, &val);
if (rc)
- ret = http_error(conn, method, url,
+ ret = http_response(conn, method, url,
MHD_HTTP_INTERNAL_SERVER_ERROR);
else
- ret = httpd_json_response(conn, url, method, val);
+ ret = httpd_json_response(conn, url, method, MHD_HTTP_OK, val);
freeaddrinfo(res);
return ret;
}
typedef int (*ENDPOINT_HANDLER)(struct MHD_Connection *,
- const char *, const char *, const char *);
+ const char *, const char *, const char *,
+ struct json_value *);
enum {
EPT_EXACT = 0x01,
@@ -449,6 +482,7 @@ struct endpoint {
static struct endpoint endpoint[] = {
{ "/config/ip-list", EPT_PREFIX, MHD_HTTP_METHOD_PUT, ept_ip_put },
+ { "/config/ip-list", EPT_PREFIX, MHD_HTTP_METHOD_POST, ept_ip_post },
{ "/config/ip-list", EPT_PREFIX, MHD_HTTP_METHOD_DELETE, ept_ip_delete },
{ "/config", EPT_PREFIX, MHD_HTTP_METHOD_GET, ept_config },
{ "/host", EPT_PREFIX, MHD_HTTP_METHOD_GET, ept_host_stat },
@@ -457,28 +491,67 @@ static struct endpoint endpoint[] = {
{ NULL }
};
-static ENDPOINT_HANDLER
-find_endpoint_handler(char const *url, char const *method, char const **suffix)
+static int
+find_endpoint_handler(char const *url, char const *method,
+ ENDPOINT_HANDLER *ret_handler, char const **ret_suffix)
{
struct endpoint *ept;
+ int urlmatch = 0;
for (ept = endpoint; ept->url; ept++) {
- if (strcmp(ept->method, method))
- continue;
if (ept->flags & EPT_EXACT) {
if (strcmp(ept->url, url) == 0) {
- *suffix = url + strlen(url);
- return ept->handler;
+ if (strcmp(ept->method, method)) {
+ urlmatch++;
+ continue;
+ }
+ *ret_handler = ept->handler;
+ *ret_suffix = url + strlen(url);
+ return MHD_HTTP_OK;
}
} else {
size_t len = strlen(ept->url);
if (strncmp(url, ept->url, len) == 0
&& (url[len] == '/' || url[len] == 0)) {
- *suffix = url + len;
- return ept->handler;
+ if (strcmp(ept->method, method)) {
+ urlmatch++;
+ continue;
+ }
+ *ret_handler = ept->handler;
+ *ret_suffix = url + len;
+ return MHD_HTTP_OK;
}
}
}
- return NULL;
+ return urlmatch ? MHD_HTTP_METHOD_NOT_ALLOWED : MHD_HTTP_NOT_FOUND;
+}
+
+struct postbuf {
+ char *base;
+ size_t size;
+ size_t len;
+ ENDPOINT_HANDLER handler;
+ char suffix[1];
+};
+
+static void
+postbuf_free(struct postbuf *pb)
+{
+ free(pb->base);
+ free(pb);
+}
+
+static int
+postbuf_add(struct postbuf *pb, const char *str, size_t len)
+{
+ while (pb->len + len >= pb->size) {
+ char *np = json_2nrealloc(pb->base, &pb->size, 1);
+ if (!np)
+ return -1;
+ pb->base = np;
+ }
+ memcpy(pb->base + pb->len, str, len);
+ pb->len += len;
+ return 0;
}
static int
@@ -491,15 +564,78 @@ p903_httpd_handler(void *cls,
{
ENDPOINT_HANDLER handler;
char const *suffix;
-
- handler = find_endpoint_handler(url, method, &suffix);
- if (handler)
- return handler(conn, url, method, suffix);
-
- if (strcmp(method, MHD_HTTP_METHOD_GET))
- return http_error(conn, method, url,
- MHD_HTTP_METHOD_NOT_ALLOWED);
- return http_error(conn, method, url, MHD_HTTP_FORBIDDEN);
+ int status;
+
+ if (strcmp(method, MHD_HTTP_METHOD_POST) == 0) {
+ struct postbuf *pb;
+
+ if (*con_cls == NULL) {
+ char const *ctype;
+
+ status = find_endpoint_handler(url, method, &handler,
+ &suffix);
+ if (status != MHD_HTTP_OK)
+ return http_response(conn, method, url, status);
+
+ ctype = MHD_lookup_connection_value(conn,
+ MHD_HEADER_KIND,
+ MHD_HTTP_HEADER_CONTENT_TYPE);
+ if (!ctype || strcmp(ctype, "application/json"))
+ return http_response(conn, method, url,
+ MHD_HTTP_NOT_ACCEPTABLE);
+
+ pb = malloc(sizeof(*pb) + strlen(suffix));
+ if (!pb)
+ return http_response(conn, method, url,
+ MHD_HTTP_INTERNAL_SERVER_ERROR);
+ pb->base = NULL;
+ pb->size = 0;
+ pb->len = 0;
+ pb->handler = handler;
+ strcpy(pb->suffix, suffix);
+ *con_cls = pb;
+ } else {
+ pb = *con_cls;
+ if (*upload_data_size != 0) {
+ if (postbuf_add(pb, upload_data,
+ *upload_data_size)) {
+ postbuf_free(pb);
+ return http_response(conn, method, url,
+ MHD_HTTP_INTERNAL_SERVER_ERROR);
+ }
+ *upload_data_size = 0;
+ } else {
+ char *endp;
+ int rc;
+ struct json_value *jv;
+
+ if (postbuf_add(pb, "", 1)) {
+ postbuf_free(pb);
+ return http_response(conn, method, url,
+ MHD_HTTP_INTERNAL_SERVER_ERROR);
+ }
+ rc = json_parse_string(pb->base, &jv, &endp);
+ if (rc != JSON_E_NOERR) {
+ error("%s: %s near #%d", url,
+ json_strerror(rc), endp - pb->base);
+ return http_response(conn, method, url,
+ MHD_HTTP_BAD_REQUEST);
+ }
+ rc = pb->handler(conn, url, method, pb->suffix,
+ jv);
+ postbuf_free(pb);
+ json_value_free(jv);
+ return rc;
+ }
+ }
+ return MHD_YES;
+ }
+
+ /* For all other methods */
+ status = find_endpoint_handler(url, method, &handler, &suffix);
+ if (status != MHD_HTTP_OK)
+ return http_response(conn, method, url, status);
+ return handler(conn, url, method, suffix, NULL);
}
void

Return to:

Send suggestions and report system problems to the System administrator.