aboutsummaryrefslogtreecommitdiff
path: root/alarmd
diff options
context:
space:
mode:
authorDavid Phillips <david@sighup.nz>2018-06-04 00:09:02 +1200
committerDavid Phillips <david@sighup.nz>2018-06-04 00:09:02 +1200
commit5f5316a034d68f8825a16e7b866c8e8b2b6c6bd8 (patch)
treeba8d8b59113aa0ec02b92cf14a50e2cef0913684 /alarmd
downloadalarmd-5f5316a034d68f8825a16e7b866c8e8b2b6c6bd8.tar.xz
Initial dump of prototype
Diffstat (limited to 'alarmd')
-rw-r--r--alarmd/Makefile4
-rw-r--r--alarmd/alarmd.c207
2 files changed, 211 insertions, 0 deletions
diff --git a/alarmd/Makefile b/alarmd/Makefile
new file mode 100644
index 0000000..b6c56d9
--- /dev/null
+++ b/alarmd/Makefile
@@ -0,0 +1,4 @@
+LDFLAGS += -L../lib -lalarm -luuid
+CFLAGS += -I../inc
+
+all: alarmd
diff --git a/alarmd/alarmd.c b/alarmd/alarmd.c
new file mode 100644
index 0000000..239fc3b
--- /dev/null
+++ b/alarmd/alarmd.c
@@ -0,0 +1,207 @@
+#include <stdio.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netdb.h>
+#include <strings.h>
+#include <uuid/uuid.h>
+#include <uthash.h>
+
+#include "alarmd_proto.h"
+
+struct alarm {
+ UT_hash_handle hh;
+ char uuid[16];
+ char *name;
+ bool is_raised;
+// time_t last_change;
+};
+
+static struct alarm *alarms;
+
+int8_t read_string(int sock, char (*buffer)[128])
+{
+ uint8_t length = 0;
+ if (recv(sock, &length, sizeof(uint8_t), 0) < sizeof(uint8_t)) {
+ return -1;
+ }
+ if (length >= 128) {
+ return -1;
+ }
+ if (recv(sock, buffer, length, 0) < 0) {
+ return -1;
+ }
+ (*buffer)[length] = '\0';
+ return length;
+}
+
+int main(void)
+{
+ int sock = 0;
+ int c_sock = 0;
+ socklen_t c_addr_l = 0;
+ struct addrinfo hints, *s_info, *p;
+ struct sockaddr_storage c_addr;
+ char buffer[128];
+ uint32_t packet_type = 0;
+ ssize_t nread = 0;
+ uint32_t count = 0;
+
+ int reuse = 1;
+
+ uuid_t uuid;
+ char uuid_str[37];
+ struct alarm *target = NULL;
+
+ bzero(&hints, sizeof(hints));
+ hints.ai_family = AF_UNSPEC;
+ hints.ai_socktype = SOCK_STREAM;
+ hints.ai_flags = AI_PASSIVE;
+
+ if (getaddrinfo(NULL, ALARMD_PORT, &hints, &s_info) < 0) {
+ perror("getaddrinfo");
+ return 1;
+ }
+
+ for (p = s_info; p != NULL; p = p->ai_next) {
+ if ((sock = socket(p->ai_family, p->ai_socktype, p->ai_protocol)) < 0) {
+ perror("socket");
+ continue;
+ }
+ if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse)) < 0) {
+ perror("setsockopt");
+ return 1;
+ }
+ if (bind(sock, p->ai_addr, p->ai_addrlen) < 0) {
+ perror("bind");
+ continue;
+ }
+ break;
+ }
+
+ if (!p) {
+ fprintf(stderr, "No addresses to bind to\n");
+ return 1;
+ }
+
+ freeaddrinfo(s_info);
+
+ if (listen(sock, 128) < 0) {
+ perror("listen");
+ return 1;
+ }
+
+ c_addr_l = sizeof(c_addr);
+ if ((c_sock = accept(sock, (struct sockaddr *)&c_addr, &c_addr_l)) < 0) {
+ perror("accept");
+ return 1;
+ }
+
+ while (1) {
+ /* read packet type */
+ nread = recv(c_sock, &packet_type, sizeof(packet_type), 0);
+ if (nread < 0) {
+ perror("read");
+ return 1;
+ } else if (nread < sizeof(packet_type)) {
+ fprintf(stderr, "Packet type too short\n");
+ return 1;
+ }
+ packet_type = ntohl(packet_type);
+
+ switch(packet_type) {
+ case ALARMD_PACKET_TYPE_REGISTER:
+ if (read_string(c_sock, &buffer) < 0) {
+ return 1;
+ }
+ uuid_generate(uuid);
+ //uuid_unparse(uuid, uuid_str);
+ //fprintf(stderr, "Registering alarm %s with uuid %s\n", buffer, uuid_str);
+ if (send(c_sock, uuid, sizeof(uuid), 0) != sizeof(uuid)) {
+ perror("send");
+ return 1;
+ }
+ struct alarm *new_alarm = malloc(sizeof(*new_alarm));
+ if (new_alarm == NULL) {
+ perror("malloc");
+ return 1;
+ }
+ new_alarm->name = strdup(buffer);
+ memcpy(new_alarm->uuid, uuid, 16);
+ new_alarm->is_raised = 0;
+ HASH_ADD(hh, alarms, uuid, 16, new_alarm);
+ break;
+ case ALARMD_PACKET_TYPE_DEREGISTER:
+ /* FIXME 16 magic */
+ if (recv(c_sock, &buffer, 16, 0) < 16) {
+ return 1;
+ }
+ uuid_unparse(buffer, uuid_str);
+ fprintf(stderr, "Deregistering alarm %s\n", uuid_str);
+ HASH_FIND(hh, alarms, buffer, 16, target);
+ if (target != NULL) {
+ HASH_DEL(alarms, target);
+ free(target);
+ }
+ break;
+ case ALARMD_PACKET_TYPE_RAISE:
+ /* FIXME 16 magic */
+ if (recv(c_sock, &buffer, 16, 0) < 16) {
+ return 1;
+ }
+ uuid_unparse(buffer, uuid_str);
+ fprintf(stderr, "Raising alarm %s\n", uuid_str);
+ HASH_FIND(hh, alarms, buffer, 16, target);
+ if (target != NULL) {
+ target->is_raised = 1;
+ }
+ break;
+ case ALARMD_PACKET_TYPE_CLEAR:
+ /* FIXME 16 magic */
+ if (recv(c_sock, &buffer, 16, 0) < 16) {
+ return 1;
+ }
+ uuid_unparse(buffer, uuid_str);
+ fprintf(stderr, "Clearing alarm %s\n", uuid_str);
+ HASH_FIND(hh, alarms, buffer, 16, target);
+ if (target != NULL) {
+ target->is_raised = 0;
+ }
+ break;
+ case ALARMD_PACKET_TYPE_QUERY:
+ /* bounds-check HASH_COUNT*/
+ count = htonl(HASH_COUNT(alarms));
+ uint8_t length = 0;
+ /* FIXME */
+ struct alarm *a = NULL;
+ struct alarm *tmp = NULL;
+ HASH_ITER(hh, alarms, a, tmp) {
+ fprintf(stderr, "DEBUG : [%s] %s\n", a->is_raised ? "RAISE" : "CLEAR" , a->name);
+ if (send(c_sock, &count, sizeof(count), 0) < sizeof(count)) {
+ perror("send");
+ }
+ /* FIXME factor out, idiot. also bounds check on strlen */
+ length = strlen(a->name);
+ if (send(c_sock, &length, sizeof(length), 0) < sizeof(length)) {
+ perror("send");
+ }
+ if (send(c_sock, a->name, strlen(a->name), 0) < strlen(a->name)) {
+ perror("send");
+ }
+ if (send(c_sock, &(a->is_raised), sizeof(a->is_raised), 0) < sizeof(a->is_raised)) {
+ perror("send");
+ }
+ fprintf(stderr, "SENT.\n");
+ }
+ break;
+ default:
+ fprintf(stderr, "Unknown packet type %d\n", packet_type);
+ break;
+ }
+ }
+ fprintf(stderr, "Server stopping\n");
+ close(sock);
+}