1 /* Direct Query Server module for srvx 1.x
2 * Copyright 2006 Michael Poole <mdpoole@troilus.org>
4 * This file is part of srvx.
6 * srvx is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with srvx; if not, write to the Free Software Foundation,
18 * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
28 const char *qserver_module_deps[] = { NULL };
30 struct qserverClient {
31 struct userNode *user;
34 unsigned int password_ok : 1;
37 static struct log_type *qserver_log;
38 static struct io_fd *qserver_listener;
39 static struct qserverClient **qserver_clients;
40 static dict_t qserver_dict;
41 static unsigned int qserver_nbots;
48 qserver_privmsg(struct userNode *user, struct userNode *target, const char *text, UNUSED_ARG(int server_qualified))
50 struct qserverClient *client;
52 client = dict_find(qserver_dict, target->nick, NULL);
53 assert(client->user == target);
54 ioset_printf(client->fd, "%s P :%s\n", user->nick, text);
58 qserver_notice(struct userNode *user, struct userNode *target, const char *text, UNUSED_ARG(int server_qualified))
60 struct qserverClient *client;
62 client = dict_find(qserver_dict, target->nick, NULL);
63 assert(client->user == target);
64 ioset_printf(client->fd, "%s N :%s\n", user->nick, text);
68 qserver_readable(struct io_fd *fd)
70 struct qserverClient *client;
71 struct service *service;
72 char *argv[MAXNUMPARAMS];
79 assert(client->fd == fd);
80 res = ioset_line_read(fd, tmpline, sizeof(tmpline));
87 len = strlen(tmpline);
88 while (tmpline[len - 1] == '\r' || tmpline[len - 1] == '\n')
89 tmpline[--len] = '\0';
90 argc = split_line(tmpline, false, ArrayLength(argv), argv);
92 ioset_printf(fd, "MISSING_ARGS");
95 if (!strcmp(argv[1], "PASS")
97 && !strcmp(argv[2], conf.password)) {
98 client->password_ok = 1;
99 } else if ((client->password_ok || !conf.password)
100 && (service = service_find(argv[1])) != NULL) {
101 ioset_printf(fd, "%s S\n", argv[0]);
102 svccmd_invoke_argv(client->user, service, NULL, argc - 2, argv + 2, 1);
103 ioset_printf(fd, "%s E\n", argv[0]);
105 ioset_printf(fd, "%s X %s\n", argv[0], argv[1]);
110 qserver_destroy_fd(struct io_fd *fd)
112 struct qserverClient *client;
115 assert(client->fd == fd);
116 dict_remove(qserver_dict, client->user->nick);
117 DelUser(client->user, NULL, 0, "client disconnected");
118 qserver_clients[client->id] = NULL;
123 qserver_accept(UNUSED_ARG(struct io_fd *listener), struct io_fd *fd)
125 struct qserverClient *client;
126 struct sockaddr_storage ss;
131 char nick[NICKLEN+1];
132 char host[HOSTLEN+1];
135 client = calloc(1, sizeof(*client));
139 fd->readable_cb = qserver_readable;
140 fd->destroy_cb = qserver_destroy_fd;
142 for (ii = 0; ii < qserver_nbots; ++ii)
143 if (qserver_clients[ii] == NULL)
145 if (ii == qserver_nbots) {
147 qserver_clients = realloc(qserver_clients, qserver_nbots * sizeof(qserver_clients[0]));
148 for (jj = ii; jj < qserver_nbots; ++jj)
149 qserver_clients[jj] = NULL;
153 qserver_clients[client->id] = client;
154 snprintf(nick, sizeof(nick), " QServ%04d", client->id);
155 safestrncpy(host, "srvx.dummy.user", sizeof(host));
156 safestrncpy(ip, "0.0.0.0", sizeof(ip));
158 res = getpeername(fd->fd, (struct sockaddr*)&ss, &sa_len);
160 getnameinfo((struct sockaddr*)&ss, sa_len, ip, sizeof(host), NULL, 0, NI_NUMERICHOST);
161 if (getnameinfo((struct sockaddr*)&ss, sa_len, host, sizeof(host), NULL, 0, 0) != 0)
162 safestrncpy(host, ip, sizeof(host));
164 client->user = AddLocalUser(nick, nick+1, host, "qserver dummy user", "*+i");
165 irc_pton(&client->user->ip, NULL, ip);
166 dict_insert(qserver_dict, client->user->nick, client);
168 reg_privmsg_func(client->user, qserver_privmsg);
169 reg_notice_func(client->user, qserver_notice);
173 qserver_conf_read(void)
175 struct addrinfo hints;
182 ioset_close(qserver_listener, 1);
183 qserver_listener = NULL;
184 node = conf_get_data("modules/qserver", RECDB_OBJECT);
187 str1 = database_get_data(node, "address", RECDB_QSTRING);
188 str2 = database_get_data(node, "port", RECDB_QSTRING);
191 memset(&hints, 0, sizeof(hints));
192 hints.ai_flags = AI_PASSIVE;
193 hints.ai_socktype = SOCK_STREAM;
194 res = getaddrinfo(str1, str2, &hints, &ai);
196 log_module(qserver_log, LOG_ERROR, "Unable to find address [%s]:%s: %s", str1 ? str1 : "", str2, gai_strerror(res));
197 } else if (!(qserver_listener = ioset_listen(ai->ai_addr, ai->ai_addrlen, NULL, qserver_accept))) {
198 log_module(qserver_log, LOG_ERROR, "Unable to listen on [%s]:%s", str1 ? str1 : "", str2);
200 conf.password = database_get_data(node, "password", RECDB_QSTRING);
205 qserver_cleanup(void)
209 for (ii = 0; ii < qserver_nbots; ++ii)
210 if (qserver_clients[ii])
211 DelUser(qserver_clients[ii]->user, NULL, 0, "module finalizing");
212 dict_delete(qserver_dict);
218 qserver_log = log_register_type("QServer", "file:qserver.log");
219 conf_register_reload(qserver_conf_read);
220 qserver_dict = dict_new();
221 reg_exit_func(qserver_cleanup);
226 qserver_finalize(void)