#include #include #include #include #include #include #include #include #include #include #include #include #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, unsigned 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 handle_register(int c_sock) { uuid_t uuid; unsigned char buffer[128]; struct alarm *new_alarm = NULL; 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; } if ((new_alarm = malloc(sizeof(*new_alarm))) == NULL) { perror("malloc"); return 1; } new_alarm->name = strdup((const char*)buffer); memcpy(new_alarm->uuid, uuid, 16); new_alarm->is_raised = 0; /* LOCK */ HASH_ADD(hh, alarms, uuid, 16, new_alarm); /* UNLOCK */ return 0; } int handle_deregister(int c_sock) { unsigned char buffer[128]; struct alarm *target = NULL; char uuid_str[37]; /* 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); /* LOCK */ HASH_FIND(hh, alarms, buffer, 16, target); if (target != NULL) { HASH_DEL(alarms, target); free(target); } /* UNLOCK */ return 0; } int handle_set_raised_generic(int c_sock, int shall_raise) { unsigned char buffer[128]; struct alarm *target = NULL; char uuid_str[37]; /* FIXME 16 magic */ if (recv(c_sock, &buffer, 16, 0) < 16) { return 1; } uuid_unparse(buffer, uuid_str); fprintf(stderr, "%sing alarm %s\n", shall_raise ? "Rais" : "Clear", uuid_str); /* LOCK */ HASH_FIND(hh, alarms, buffer, 16, target); if (target != NULL) { target->is_raised = shall_raise; } /* UNLOCK */ return 0; } int handle_raise(int c_sock) { return handle_set_raised_generic(c_sock, 1); } int handle_clear(int c_sock) { return handle_set_raised_generic(c_sock, 0); } int handle_query(int c_sock) { uint32_t count = 0; uint8_t length = 0; struct alarm *a = NULL; struct alarm *tmp = NULL; /* LOCK */ count = htonl(HASH_COUNT(alarms)); if (send(c_sock, &count, sizeof(count), 0) < sizeof(count)) { perror("send"); } HASH_ITER(hh, alarms, a, tmp) { fprintf(stderr, "DEBUG : [%s] %s\n", a->is_raised ? "RAISE" : "CLEAR" , a->name); /* 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"); } /* UNLOCK */ return 0; } int main(int argc, char **argv) { int sock = 0; int c_sock = 0; socklen_t c_addr_l = 0; struct sockaddr_un local, c_addr; uint32_t packet_type = 0; ssize_t nread = 0; if (argc != 2) { fprintf(stderr, "Syntax: %s socket_name\n", argv[0]); return 1; } if ((sock = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) { perror("socket"); return 1; } local.sun_family = AF_UNIX; strcpy(local.sun_path, argv[1]); unlink(local.sun_path); if (bind(sock, (struct sockaddr *)&local, strlen(local.sun_path) + sizeof(local.sun_family)) < 0) { perror("bind"); return 1; } 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("recv"); return 1; } else if (nread == 0) { break; } 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 (handle_register(c_sock)) { close(c_sock); } break; case ALARMD_PACKET_TYPE_DEREGISTER: if (handle_deregister(c_sock)) { close(c_sock); } break; case ALARMD_PACKET_TYPE_RAISE: if (handle_raise(c_sock)) { close(c_sock); } break; case ALARMD_PACKET_TYPE_CLEAR: if (handle_clear(c_sock)) { close(c_sock); } break; case ALARMD_PACKET_TYPE_QUERY: if (handle_query(c_sock)) { close(c_sock); } break; default: fprintf(stderr, "Unknown packet type %d\n", packet_type); break; } } fprintf(stderr, "Server stopping\n"); close(sock); }