/* * 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); static int does_my_kokoro_go_doki_doki(struct tlv *tlv); /* 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_packet pack; struct tlv field; struct timespec t; char *buf = NULL; size_t recvsize; int ret = A_OK; t = *iter_len; tlv_packet_init(&pack); while (ret != ERROR) { ret = net_getlastdata(__progstate.nd, &buf, &recvsize); if (ret != A_OK) { goto skiprecv; } /* 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); /* handles discovery */ if (ret != A_OK || !(does_my_kokoro_go_doki_doki(&field))) { goto skiprecv; } /* handles receiving messages */ if (field.head.type == TEXT) { message_receive(field.data); } /* jumping here if did not receive any data */ skiprecv: /* handles sending messages */ if (message_send(&field)) { if (field.head.size) { tlv_pack(&pack, &field); tlv_packet_finalize(&pack); tlv_destroy(&field); net_send(__progstate.nd, pack.data, pack.cursor); tlv_packet_reset(&pack); } } nanosleep(&t, NULL); } tlv_packet_destroy(&pack); return ret; } static int does_my_kokoro_go_doki_doki(struct tlv *tlv) { int ret = ERROR; static struct tlv_packet pack; static size_t firstrun = 1; if (firstrun) { struct tlv field; 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); firstrun = 0; } if (tlv->head.type == HEARTBEAT && !(strcmp(tlv->data, heartbeat_device))) { if (setting_verbose() >= INFO) { fprintf(stderr, "heartbeat.\n"); } ret = net_send(__progstate.nd, pack.data, pack.cursor); } return ret; } static void cleanup(void) { purple_close(); proto_stdio_close(); net_close(__progstate.nd); __progstate.nd = 0; settings_cleanup(); }