1 /* module.c - NeonServ v5.6
2 * Copyright (C) 2011-2012 Philipp Kreil (pk910)
4 * This program is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation, either version 3 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 #include "../module.h"
18 #include "../../timeq.h"
19 #include "../../ConfigParser.h"
20 #include "../../mysqlConn.h"
21 #include "../../ClientSocket.h"
22 #include "../../UserNode.h"
24 #define STATS_UPDATE_SECONDS 1800
25 #define STATS_UPDATE_HOST "neonserv.krypton-bouncer.de"
26 #define STATS_UPDATE_PORT 1675
27 #define STATS_IDENTIFIER_LEN 10
28 #define STATS_IDENTIFIER_POOL "abcdefghijklmnopqrstuvwxyz0123456789#*+-_.:;,!ยง$%&/()=?[]{}<>|@"
29 #define STATS_IDENTIFIER_POOL_SIZE 63
31 static TIMEQ_CALLBACK(stats_timer_callback);
33 static int module_initialize() {
37 static void module_start(int type) {
38 if(!timeq_name_exists("stats"))
39 timeq_add_name("stats", 60, module_id, stats_timer_callback, NULL);
42 static void module_stop(int type) {
43 timeq_del_name("stats");
46 static char *get_identifier() {
49 printf_mysql_query("SELECT `value` FROM `settings` WHERE `name` = 'identifier'");
51 if(!(row = mysql_fetch_row(res))) {
53 char identifier[STATS_IDENTIFIER_LEN+1];
55 char *pool = STATS_IDENTIFIER_POOL;
56 for(i = 0; i < STATS_IDENTIFIER_LEN; i++) {
57 identifier[i] = pool[(rand() % STATS_IDENTIFIER_POOL_SIZE)];
60 printf_mysql_query("INSERT INTO `settings` (`name`, `value`) VALUES ('identifier', '%s')", escape_string(identifier));
61 printf_mysql_query("SELECT `value` FROM `settings` WHERE `name` = 'identifier'");
63 row = mysql_fetch_row(res);
66 if(strlen(row[0]) < 10) return NULL;
70 static TIMEQ_CALLBACK(stats_timer_callback) {
71 timeq_add_name("stats", STATS_UPDATE_SECONDS, module_id, stats_timer_callback, NULL);
75 char *modname = get_module_name(module_id);
76 char *bot_identifier = get_identifier();
77 if(!bot_identifier) return;
78 //build update package
79 pkgpos += sprintf(pkgbuf + pkgpos, "nsupdate\n%s\n%s.%d %s\n", bot_identifier, NEONSERV_VERSION, get_patchlevel(), (strcmp(get_revision(), "") ? get_revision() : "-"));
80 sprintf(tmp, "modules/%s/hide_networkname", modname);
81 if(get_int_field(tmp))
82 pkgpos += sprintf(pkgbuf + pkgpos, "*\n");
84 struct ClientSocket *bot;
85 for(bot = getBots(SOCKET_FLAG_READY, NULL); bot; bot = getBots(SOCKET_FLAG_READY, bot)) {
86 if(bot->network_name) break;
89 pkgpos += sprintf(pkgbuf + pkgpos, "%s\n", bot->network_name);
91 pkgpos += sprintf(pkgbuf + pkgpos, "?\n");
93 sprintf(tmp, "modules/%s/hide_botnick", modname);
94 if(get_int_field(tmp))
95 pkgpos += sprintf(pkgbuf + pkgpos, "*\n");
97 struct ClientSocket *bot, *bot1 = NULL, *bot2 = NULL, *bot3 = NULL;
98 for(bot = getBots(SOCKET_FLAG_READY, NULL); bot; bot = getBots(SOCKET_FLAG_READY, bot)) {
99 if(bot->botid == 1 && (bot->flags & SOCKET_FLAG_PREFERRED))
101 else if((bot->flags & SOCKET_FLAG_PREFERRED))
113 pkgpos += sprintf(pkgbuf + pkgpos, "%s!%s@%s %d\n", (bot->user ? bot->user->nick : "*"), (bot->user ? bot->user->ident : "*"), (bot->host ? bot->host : "*"), bot->port);
115 pkgpos += sprintf(pkgbuf + pkgpos, "?\n");
117 sprintf(tmp, "modules/%s/hide_chancount", modname);
118 if(get_int_field(tmp))
119 pkgpos += sprintf(pkgbuf + pkgpos, "*\n");
121 int channel_count = getChannelCount();
122 pkgpos += sprintf(pkgbuf + pkgpos, "%d\n", channel_count);
124 sprintf(tmp, "modules/%s/hide_usercount", modname);
125 if(get_int_field(tmp))
126 pkgpos += sprintf(pkgbuf + pkgpos, "*\n");
128 int user_count = getUserCount();
129 int chanuser_count = getChanUserCount();
130 pkgpos += sprintf(pkgbuf + pkgpos, "%d %d\n", user_count, chanuser_count);
132 pkgpos += sprintf(pkgbuf + pkgpos, "%lu\n", getStartTime());
136 struct sockaddr_in si_other;
137 int sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
138 if (sock == -1) return;
139 memset((char *) &si_other, 0, sizeof(si_other));
140 si_other.sin_family = AF_INET;
141 si_other.sin_port = htons(STATS_UPDATE_PORT);
142 if (!inet_aton(STATS_UPDATE_HOST, &si_other.sin_addr)) {
143 struct hostent *host = gethostbyname(STATS_UPDATE_HOST);
145 si_other.sin_addr = *(struct in_addr*)host->h_addr;
147 sendto(sock, pkgbuf, pkgpos, 0, &si_other, sizeof(si_other));
149 struct sockaddr_in si_other;
150 int sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
151 if (sock == -1) return;
152 si_other.sin_family = AF_INET;
153 si_other.sin_port = htons(STATS_UPDATE_PORT);
154 si_other.sin_addr.s_addr = inet_addr(STATS_UPDATE_HOST);
155 if (si_other.sin_addr.s_addr == INADDR_NONE) {
156 struct hostent *host = gethostbyname(STATS_UPDATE_HOST);
158 memcpy(&(si_other.sin_addr), host->h_addr_list[0], 4);
160 sendto(sock, pkgbuf, pkgpos, 0, (struct sockaddr *) &si_other, sizeof(si_other));
165 MODULE_HEADER(module_initialize, module_start, module_stop);