summaryrefslogtreecommitdiff
path: root/main.c
diff options
context:
space:
mode:
Diffstat (limited to 'main.c')
-rw-r--r--main.c84
1 files changed, 58 insertions, 26 deletions
diff --git a/main.c b/main.c
index 9b5c666..31e78cc 100644
--- a/main.c
+++ b/main.c
@@ -19,14 +19,26 @@
#include <luajit.h>
#include <mosquitto.h>
#include <signal.h>
+#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/epoll.h>
+#include <sys/uio.h>
#include <unistd.h>
#include "logging.h"
#include "server.h"
+#define UNCONST(op) ((void*)(uintptr_t)(op))
+#define STRIOVEC(op) \
+ { .iov_base = UNCONST(op), .iov_len = sizeof(op) - 1 }
+#define FLUSHARG(op) \
+ { STRIOVEC(op), {.iov_base = NULL, .iov_len = 0}, }
+
+struct Context {
+ struct mosquitto* mosq;
+};
+
static volatile sig_atomic_t g_shutdown;
static void OnSignal(int num) {
@@ -34,34 +46,53 @@ static void OnSignal(int num) {
g_shutdown = 1;
}
+static bool Flush(int fd, const struct iovec iov[2]) {
+ // TODO(mburakov): Change to iterative writing.
+ ssize_t result = writev(fd, iov, 2);
+ if (result != (ssize_t)(iov[0].iov_len + iov[1].iov_len)) {
+ Log("Failed to write complete reply (%s)", strerror(errno));
+ return false;
+ }
+ return true;
+}
+
static bool HandleRequest(void* user, int fd, const char* method,
const char* target, const void* body,
size_t body_size) {
- const char* reply = NULL;
+ struct Context* context = user;
if (strcmp(method, "POST")) {
- reply =
+ static const struct iovec kStatus405[2] = FLUSHARG(
"HTTP/1.1 405 Method Not Allowed\r\n"
"Content-Length: 0\r\n"
- "\r\n";
- } else if (!body_size) {
- reply =
+ "\r\n");
+ return Flush(fd, kStatus405);
+ }
+ if (!body_size || !target[1]) {
+ static const struct iovec kStatus400[2] = FLUSHARG(
"HTTP/1.1 400 Bad Request\r\n"
"Content-Length: 0\r\n"
- "\r\n";
- } else {
- reply =
+ "\r\n");
+ return Flush(fd, kStatus400);
+ }
+ int mosq_errno = mosquitto_publish(context->mosq, NULL, target + 1,
+ (int)body_size, body, 0, false);
+ if (mosq_errno == MOSQ_ERR_SUCCESS) {
+ static const struct iovec kStatus200[2] = FLUSHARG(
"HTTP/1.1 200 OK\r\n"
"Content-Length: 0\r\n"
- "\r\n";
- }
- // TODO(mburakov): Change to iterative writing.
- size_t length = strlen(reply);
- ssize_t result = write(fd, reply, length);
- if (result != (ssize_t)length) {
- Log("Failed to write complete reply (%s)", strerror(errno));
- return 0;
+ "\r\n");
+ return Flush(fd, kStatus200);
}
- return 1;
+ char buffer[64];
+ const char* error = mosquitto_strerror(mosq_errno);
+ snprintf(buffer, sizeof(buffer),
+ "HTTP/1.1 500 Internal Server Error\r\n"
+ "Content-Length: %zu\r\n\r\n",
+ strlen(error));
+ const struct iovec iov[2] = {
+ {.iov_base = buffer, .iov_len = strlen(buffer)},
+ {.iov_base = UNCONST(error), .iov_len = strlen(error)}};
+ return Flush(fd, iov);
}
int main(int argc, char* argv[]) {
@@ -72,7 +103,8 @@ int main(int argc, char* argv[]) {
int epfd = epoll_create(1);
if (epfd == -1) Terminate("Failed to create epoll (%s)", strerror(errno));
int result = EXIT_FAILURE;
- struct Server* server = ServerCreate(epfd, HandleRequest, NULL);
+ struct Context context;
+ struct Server* server = ServerCreate(epfd, HandleRequest, &context);
if (!server) {
Log("Failed to create server");
goto rollback_epoll_create;
@@ -83,17 +115,17 @@ int main(int argc, char* argv[]) {
mosquitto_strerror(mosq_errno));
goto rollback_server_create;
}
- struct mosquitto* mosq = mosquitto_new(NULL, true, NULL);
- if (!mosq) {
+ context.mosq = mosquitto_new(NULL, true, NULL);
+ if (!context.mosq) {
Log("Failed to create mosquitto (%s)", strerror(errno));
goto rollback_mosquitto_lib_init;
}
- mosq_errno = mosquitto_connect(mosq, argv[1], port, 60);
+ mosq_errno = mosquitto_connect(context.mosq, argv[1], port, 60);
if (mosq_errno != MOSQ_ERR_SUCCESS) {
Log("Failed to connect mosquitto (%s)", mosquitto_strerror(mosq_errno));
goto rollback_mosquitto_new;
}
- int mosq_sock = mosquitto_socket(mosq);
+ int mosq_sock = mosquitto_socket(context.mosq);
if (mosq_sock == -1) {
Log("Failed to get mosquitto socket");
goto rollback_mosquitto_connect;
@@ -115,7 +147,7 @@ int main(int argc, char* argv[]) {
if (errno != EINTR) goto rollback_mosquitto_connect;
continue;
case 0:
- mosq_errno = mosquitto_loop_misc(mosq);
+ mosq_errno = mosquitto_loop_misc(context.mosq);
if (mosq_errno != MOSQ_ERR_SUCCESS) {
Log("Failed to loop mosquitto (%s)", mosquitto_strerror(mosq_errno));
goto rollback_mosquitto_connect;
@@ -125,7 +157,7 @@ int main(int argc, char* argv[]) {
break;
}
if (ev.data.fd == mosq_sock) {
- mosq_errno = mosquitto_loop_read(mosq, 1);
+ mosq_errno = mosquitto_loop_read(context.mosq, 1);
if (mosq_errno != MOSQ_ERR_SUCCESS) {
Log("Failed to read mosquitto (%s)", mosquitto_strerror(mosq_errno));
goto rollback_mosquitto_connect;
@@ -137,9 +169,9 @@ int main(int argc, char* argv[]) {
}
result = EXIT_SUCCESS;
rollback_mosquitto_connect:
- mosquitto_disconnect(mosq);
+ mosquitto_disconnect(context.mosq);
rollback_mosquitto_new:
- mosquitto_destroy(mosq);
+ mosquitto_destroy(context.mosq);
rollback_mosquitto_lib_init:
mosquitto_lib_cleanup();
rollback_server_create: