void readsocks(const char *fname) { /* Don't bother setting this if a hub ... it is only intended to prevent parting channels (in bot_shouldjoin()) */ if (!conf.bot->hub) restarting = 1; char *nick = NULL, *jnick = NULL, *ip4 = NULL, *ip6 = NULL; time_t old_buildts = 0; bool cached_005 = 0; const char salt1[] = SALT1; EncryptedStream stream(salt1); stream.loadFile(fname); bd::String str, type; reset_chans = 0; while (stream.tell() < stream.length()) { str = stream.getline().chomp(); dprintf(DP_DEBUG, "read line: %s\n", str.c_str()); type = newsplit(str); if (type == STR("-dcc")) dprintf(DP_DEBUG, STR("Added dcc: %d\n"), dcc_read(stream)); else if (type == STR("-sock")) dprintf(DP_DEBUG, STR("Added fd: %d\n"), sock_read(stream)); else if (type == STR("+online_since")) online_since = strtol(str.c_str(), NULL, 10); else if (type == STR("+server_online")) server_online = strtol(str.c_str(), NULL, 10); else if (type == STR("+server_floodless")) floodless = 1; else if (type == STR("+in_deaf")) in_deaf = 1; else if (type == STR("+in_callerid")) in_callerid = 1; else if (type == STR("+chan")) { bd::String chname = str; channel_add(NULL, chname.c_str(), NULL); struct chanset_t* chan = findchan_by_dname(chname.c_str()); strlcpy(chan->name, chan->dname, sizeof(chan->name)); chan->status = chan->ircnet_status = 0; chan->ircnet_status |= CHAN_PEND; reset_chans = 2; } else if (type == STR("+buildts")) old_buildts = strtol(str.c_str(), NULL, 10); else if (type == STR("+botname")) nick = str.dup(); else if (type == STR("+rolls")) rolls = atoi(str.c_str()); else if (type == STR("+altnick_char")) altnick_char = str[0]; else if (type == STR("+burst")) burst = atoi(str.c_str()); else if (type == STR("+flood_count")) flood_count = atoi(str.c_str()); else if (type == STR("+my_cookie_counter")) { my_cookie_counter = strtol(str.c_str(), NULL, 10); my_cookie_counter += 100; // Increase to avoid race conditions } else if (type == STR("+ip4")) ip4 = str.dup(); else if (type == STR("+ip6")) ip6 = str.dup(); else if (type == STR("+serv_cache")) { if (!cached_005 && str.find(STR("005"))) cached_005 = 1; dprintf(DP_CACHE, "%s", str.c_str()); } } restart_time = now; if (old_buildts && buildts > old_buildts) restart_was_update = 1; tell_dcc(DP_DEBUG); tell_netdebug(DP_DEBUG); unlink(fname); if (servidx >= 0) { char nserv[50] = ""; if ((ip4 && ip6) && (strcmp(ip4, myipstr(AF_INET)) || strcmp(ip6, myipstr(AF_INET6)))) { if (tands > 0) { /* We're not linked yet.. but for future */ botnet_send_chat(-1, conf.bot->nick, STR("IP changed.")); botnet_send_bye(STR("IP changed.")); } fatal("brb", 1); } else if (conf.bot->hub) { // I became a hub during restart... disconnect from IRC. if (tands > 0) { /* We're not linked yet.. but for future */ botnet_send_chat(-1, conf.bot->nick, STR("Changing to HUB.")); botnet_send_bye(STR("Changing to HUB.")); } nuke_server("emoquit"); } else { simple_snprintf(nserv, sizeof(nserv), "%s:%d", dcc[servidx].host, dcc[servidx].port); add_server(nserv); curserv = 0; keepnick = 0; /* Wait to change nicks until relinking, fixes nick/jupenick switching issues during restart */ reset_flood(); if (!server_online) server_online = now; rehash_server(dcc[servidx].host, nick); if (cached_005) replay_cache(servidx, NULL); else dprintf(DP_DUMP, "VERSION\n"); if (!reset_chans) reset_chans = 1; } } delete[] nick; delete[] ip4; delete[] ip6; if (jnick) free(jnick); if (socksfile) free(socksfile); }
void restart(int idx) { const char *reason = updating ? STR("Updating...") : STR("Restarting..."); Tempfile *socks = new Tempfile("socks"); int fd = 0; sdprintf("%s", reason); if (tands > 0) { botnet_send_chat(-1, conf.bot->nick, (char *) reason); botnet_send_bye(reason); } /* kill all connections except STDOUT/server */ for (fd = 0; fd < dcc_total; fd++) { if (dcc[fd].type && dcc[fd].type != &SERVER_SOCKET && dcc[fd].sock != STDOUT) { if (dcc[fd].sock >= 0) killsock(dcc[fd].sock); lostdcc(fd); } } const char salt1[] = SALT1; EncryptedStream stream(salt1); /* write out all leftover dcc[] entries */ for (fd = 0; fd < dcc_total; fd++) if (dcc[fd].type && dcc[fd].sock != STDOUT) dcc_write(stream, fd); /* write out all leftover socklist[] entries */ for (fd = 0; fd < MAXSOCKS; fd++) if (socklist[fd].sock != STDOUT) sock_write(stream, fd); if (server_online) { if (botname[0]) stream << bd::String::printf(STR("+botname %s\n"), botname); if (rolls) stream << bd::String::printf(STR("+rolls %d\n"), rolls); if (altnick_char) stream << bd::String::printf(STR("+altnick_char %c\n"), altnick_char); if (burst) stream << bd::String::printf(STR("+burst %d\n"), burst); if (flood_count) stream << bd::String::printf(STR("+flood_count %d\n"), flood_count); if (my_cookie_counter) stream << bd::String::printf(STR("+my_cookie_counter %lu\n"), my_cookie_counter); stream << bd::String::printf(STR("+server_online %li\n"), (long)server_online); } stream << bd::String::printf(STR("+online_since %li\n"), (long)online_since); if (floodless) stream << bd::String::printf(STR("+server_floodless %d\n"), floodless); if (in_deaf) stream << bd::String::printf(STR("+in_deaf\n")); if (in_callerid) stream << bd::String::printf(STR("+in_callerid\n")); for (struct chanset_t *chan = chanset; chan; chan = chan->next) if (shouldjoin(chan) && (channel_active(chan) || channel_pending(chan))) stream << bd::String::printf(STR("+chan %s\n"), chan->dname); stream << bd::String::printf(STR("+buildts %li\n"), (long)buildts); stream << bd::String::printf(STR("+ip4 %s\n"), myipstr(AF_INET)); stream << bd::String::printf(STR("+ip6 %s\n"), myipstr(AF_INET6)); replay_cache(-1, &stream); stream.writeFile(socks->fd); socks->my_close(); write_userfile(idx); /* if (server_online) { do_chanset(NULL, NULL, STR("+inactive"), DO_LOCAL); dprintf(DP_DUMP, STR("JOIN 0\n")); } */ fixmod(binname); /* replace image now */ char *argv[4] = { NULL, NULL, NULL, NULL }; argv[0] = strdup(binname); if (!backgrd || term_z || sdebug) { char shit[7] = ""; simple_snprintf(shit, sizeof(shit), STR("-%s%s%s"), !backgrd ? "n" : "", term_z ? "t" : "", sdebug ? "D" : ""); argv[1] = strdup(shit); argv[2] = strdup(conf.bot->nick); } else { argv[1] = strdup(conf.bot->nick); } unlink(conf.bot->pid_file); FILE *fp = NULL; if (!(fp = fopen(conf.bot->pid_file, "w"))) return; fprintf(fp, "%d %s\n", getpid(), socks->file); fclose(fp); execvp(argv[0], &argv[0]); /* hopefully this is never reached */ putlog(LOG_MISC, "*", STR("Could not restart: %s"), strerror(errno)); return; }
void LastValueCache::run() { // One for each internal statistic (0.._statcount-1) and one for the publisher. zmq_pollitem_t items[_statcount + 1]; for (int ii = 0; ii < _statcount; ii++) { _subscriber[ii] = zmq_socket(_context, ZMQ_SUB); LOG_DEBUG("Initializing inproc://%s statistic listener", _statnames[ii].c_str()); zmq_connect(_subscriber[ii], ("inproc://" + _statnames[ii]).c_str()); zmq_setsockopt(_subscriber[ii], ZMQ_SUBSCRIBE, "", 0); } _publisher = zmq_socket(_context, ZMQ_XPUB); zmq_bind(_publisher, "tcp://*:6666"); while (!_terminate) { // Reset the poll items for (int ii = 0; ii < _statcount; ii++) { items[ii].socket = _subscriber[ii]; items[ii].fd = 0; items[ii].events = ZMQ_POLLIN; items[ii].revents = 0; } items[_statcount].socket = _publisher; items[_statcount].fd = 0; items[_statcount].events = ZMQ_POLLIN; items[_statcount].revents = 0; // Poll for an event //LOG_DEBUG("Poll for %d items", _statcount + 1); int rc = zmq_poll(items, _statcount + 1, _poll_timeout_ms); assert(rc >= 0 || errno == EINTR); for (int ii = 0; ii < _statcount; ii++) { if (items[ii].revents & ZMQ_POLLIN) { LOG_DEBUG("Update to %s statistic", _statnames[ii].c_str()); clear_cache(_subscriber[ii]); while (1) { zmq_msg_t message; zmq_msg_t *cached_message = (zmq_msg_t *)malloc(sizeof(zmq_msg_t)); int more; size_t more_size = sizeof (more); zmq_msg_init(&message); zmq_msg_init(cached_message); zmq_msg_recv(&message, _subscriber[ii], 0); zmq_msg_copy(cached_message, &message); _cache[_subscriber[ii]].push_back(cached_message); zmq_getsockopt(_subscriber[ii], ZMQ_RCVMORE, &more, &more_size); zmq_msg_send(&message, _publisher, more ? ZMQ_SNDMORE : 0); zmq_msg_close(&message); if (!more) break; // Last message frame } } } // Recognize incoming subscription events if (items[_statcount].revents & ZMQ_POLLIN) { zmq_msg_t message; zmq_msg_init(&message); zmq_msg_recv(&message, _publisher, 0); char *msg_body = (char *)zmq_msg_data(&message); if (msg_body[0] == ZMQ_NEW_SUBSCRIPTION_MARKER) { // This is a new subscription std::string topic = std::string(msg_body + 1, zmq_msg_size(&message) - 1); LOG_DEBUG("New subscription for %s", topic.c_str()); bool recognized = false; for (int ii = 0; ii < _statcount; ii++) { if (topic == _statnames[ii]) { LOG_DEBUG("Statistic found, check for cached value"); recognized = true; // Replay the cached message if one exists if (_cache.find(_subscriber[ii]) != _cache.end()) { replay_cache(_subscriber[ii]); } else { LOG_DEBUG("No cached record found, reporting empty statistic"); std::string status = "OK"; zmq_send(_publisher, _statnames[ii].c_str(), _statnames[ii].length(), ZMQ_SNDMORE); zmq_send(_publisher, status.c_str(), status.length(), 0); } } } if (!recognized) { LOG_DEBUG("Subscription for unknown stat %s", topic.c_str()); std::string status = "Unknown"; zmq_send(_publisher, topic.c_str(), topic.length(), ZMQ_SNDMORE); zmq_send(_publisher, status.c_str(), status.length(), 0); } } zmq_msg_close(&message); } } for (int ii = 0; ii < _statcount; ii++) { zmq_disconnect(_subscriber[ii], ("inproc://" + _statnames[ii]).c_str()); zmq_close(_subscriber[ii]); clear_cache(_subscriber[ii]); } zmq_unbind(_publisher, "tcp://*:6666"); zmq_close(_publisher); }