#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include static HttpServer *server = NULL; static pthread_t xmpp_thr; static XMPPComponent *jabber = NULL; static volatile uint64_t start; uint64_t ParseeUptime(void) { return UtilTsMillis() - start; } int Main(Array *args, HashMap *env) { HttpServerConfig conf; const ParseeConfig *parsee_conf; Stream *yaml; Cron *cron = NULL; start = UtilTsMillis(); memset(&conf, 0, sizeof(conf)); Log(LOG_INFO, "%s - v%s[%s] (Cytoplasm %s)", NAME, VERSION, CODE, CytoplasmGetVersionStr() ); Log(LOG_INFO, "======================="); LogConfigIndent(LogConfigGlobal()); ParseeConfigLoad("parsee.json"); ParseeConfigInit(); parsee_conf = ParseeConfigGet(); { ArgParseState state; int flag; int xmpp = 8; int http = 8; ArgParseStateInit(&state); /* TODO: Have a smarter way of generating the arg table * (with a list of structs, with a description and everything) */ while ((flag = ArgParse(&state, args, "vgH:J:")) != -1) { switch (flag) { case 'H': http = strtol(state.optArg, NULL, 10); break; case 'J': xmpp = strtol(state.optArg, NULL, 10); break; case 'g': /* Write out the config file to a YAML document */ Log(LOG_INFO, "Generating YAML..."); yaml = StreamOpen("parsee.yaml", "w"); ParseeExportConfigYAML(yaml); StreamClose(yaml); goto end; case 'v': LogConfigLevelSet(LogConfigGlobal(), LOG_DEBUG); break; case '?': Log(LOG_ERR, "INVALID ARGUMENT GIVEN"); goto end; } } ParseeSetThreads(xmpp, http); } Log(LOG_NOTICE, "Connecting to XMPP..."); jabber = XMPPInitialiseCompStream( parsee_conf->component_host, parsee_conf->component_port ); if (!XMPPAuthenticateCompStream( jabber, parsee_conf->shared_comp_secret )) { Log(LOG_ERR, "Could not connect to XMPP..."); XMPPEndCompStream(jabber); goto end; } Log(LOG_NOTICE, "Creating volatile tables..."); ParseeInitialiseJIDTable(); ParseeInitialiseOIDTable(); ParseeInitialiseHeadTable(); ParseeInitialiseNickTable(); conf.port = parsee_conf->port; conf.threads = parsee_conf->http_threads; conf.maxConnections = conf.threads << 2; conf.handlerArgs = ParseeInitData(jabber); conf.handler = ParseeRequest; Log(LOG_NOTICE, "Setting up local Matrix user..."); if (ASRegisterUser(parsee_conf, parsee_conf->sender_localpart)) { char *parsee = ParseeMXID(conf.handlerArgs); ASSetAvatar(parsee_conf, parsee, "mxc://tedomum.net/" "7e228734ec8e792960bb5633e43f0cb845f709f61825130490034651136" ); ASSetName(parsee_conf, parsee, "Parsee bridge"); Free(parsee); } Log(LOG_NOTICE, "Starting up local cronjobs..."); cron = CronCreate( 10 SECONDS ); CronEvery(cron, 5 MINUTES, ParseeCleanup, conf.handlerArgs); CronStart(cron); Log(LOG_NOTICE, "Creating XMPP listener thread..."); if (pthread_create(&xmpp_thr, NULL, ParseeXMPPThread, conf.handlerArgs)) { Log(LOG_ERR, "Couldn't start XMPP listener thread."); goto end; } server = HttpServerCreate(&conf); if (!ParseeInitialiseSignals(server, xmpp_thr, jabber)) { goto end; } HttpServerStart(server); Log(LOG_NOTICE, "Listening to MUCs..."); LogConfigIndent(LogConfigGlobal()); ParseeSendPresence(conf.handlerArgs); LogConfigUnindent(LogConfigGlobal()); LogConfigUnindent(LogConfigGlobal()); Log(LOG_INFO, "======================="); HttpServerJoin(server); end: Log(LOG_INFO, "Exiting..."); HttpServerFree(server); ParseeConfigFree(); CronStop(cron); CronFree(cron); ParseeFreeData(conf.handlerArgs); ParseeDestroyNickTable(); ParseeDestroyOIDTable(); ParseeDestroyHeadTable(); ParseeDestroyJIDTable(); return 0; }