/* * Usurpation – server daemon main logic * * Copyright (C) 2019 Gediminas Jakutis * Copyright (C) 2019 Paulius Ratkevičius * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; version 2.1 * of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */ #include #include #include #include #include #include "settings.h" #include "net.h" #include "purple.h" #include "proto_stdio.h" #include "tlv.h" #include "utils.h" static struct _state { int nd; } __progstate; static void cleanup(void); static int __main_loop(const struct timespec * const iter_len); /* the logic is a placeholder right now */ int main(int argc, char **argv) { extern const char * const version; static const struct timespec t = {0, 250 * 1000 * 1000}; /* 250ms */ char *proto; printf("Usurpation daemon version %s starting\n", version); atexit(cleanup); settings_init(); __progstate.nd = net_init(setting_port()); proto = setting_im_proto(); if (strcmp(proto, "null")) { if (purple_init() && setting_verbose()) { fprintf(stderr, "libpurple initialization failed\n"); } } else { if (proto_stdio_init() && setting_verbose()) { fprintf(stderr, "stdio interface initialization failed\n"); } } free(proto); proto = NULL; /* by default and if running by as a system service, the init system * needs to keep control of the process and thus only detach if * requested when ran manually by a user. */ if (setting_detach()) { daemon(0, 0); } return __main_loop(&t); } /* TODO: semi-stub */ static int __main_loop(const struct timespec * const iter_len) { struct tlv field; struct tlv_packet pack; struct timespec t; char *buf = NULL; size_t recvsize; int ret = A_OK; t = *iter_len; tlv_init(&field, HEARTBEAT); field.data = strdup(heartbeat_server); field.head.size = sizeof(heartbeat_server); tlv_packet_init(&pack); tlv_pack(&pack, &field); tlv_packet_finalize(&pack); tlv_destroy(&field); /* flush any pending discovery packets from the socker, * as those can be quite numerous on startup. */ net_flush_read_buffer(__progstate.nd); while (ret != ERROR) { ret = net_getlastdata(__progstate.nd, &buf, &recvsize); if (ret == A_OK) { /* we're only sending one TLV per packet as of now, * so no need to save the pointer for further parsing */ ret = tlv_get(buf, &field, NULL); if (ret == A_OK && field.head.type == HEARTBEAT && !(strcmp(field.data, heartbeat_device))) { /* error checking? what error checking? */ ret = net_send(__progstate.nd, pack.data, pack.cursor + 1); } } nanosleep(&t, NULL); } tlv_packet_destroy(&pack); return ret; } static void cleanup(void) { purple_close(); proto_stdio_close(); net_close(__progstate.nd); __progstate.nd = 0; settings_cleanup(); }