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\n");
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));
138 fd->readable_cb = qserver_readable;
139 fd->destroy_cb = qserver_destroy_fd;
141 for (ii = 0; ii < qserver_nbots; ++ii)
142 if (qserver_clients[ii] == NULL)
144 if (ii == qserver_nbots) {
146 qserver_clients = realloc(qserver_clients, qserver_nbots * sizeof(qserver_clients[0]));
147 for (jj = ii; jj < qserver_nbots; ++jj)
148 qserver_clients[jj] = NULL;
152 qserver_clients[client->id] = client;
153 snprintf(nick, sizeof(nick), " QServ%04d", client->id);
154 safestrncpy(host, "srvx.dummy.user", sizeof(host));
155 safestrncpy(ip, "0.0.0.0", sizeof(ip));
157 res = getpeername(fd->fd, (struct sockaddr*)&ss, &sa_len);
159 getnameinfo((struct sockaddr*)&ss, sa_len, ip, sizeof(host), NULL, 0, NI_NUMERICHOST);
160 if (getnameinfo((struct sockaddr*)&ss, sa_len, host, sizeof(host), NULL, 0, 0) != 0)
161 safestrncpy(host, ip, sizeof(host));
163 client->user = AddLocalUser(nick, nick+1, host, "qserver dummy user", "*+oi");
164 irc_pton(&client->user->ip, NULL, ip);
165 dict_insert(qserver_dict, client->user->nick, client);
167 reg_privmsg_func(client->user, qserver_privmsg);
168 reg_notice_func(client->user, qserver_notice);
172 qserver_conf_read(void)
174 struct addrinfo hints;
181 ioset_close(qserver_listener, 1);
182 qserver_listener = NULL;
183 node = conf_get_data("modules/qserver", RECDB_OBJECT);
186 str1 = database_get_data(node, "bind_address", RECDB_QSTRING);
188 str1 = database_get_data(node, "address", RECDB_QSTRING);
189 str2 = database_get_data(node, "port", RECDB_QSTRING);
192 memset(&hints, 0, sizeof(hints));
193 hints.ai_flags = AI_PASSIVE;
194 hints.ai_socktype = SOCK_STREAM;
195 res = getaddrinfo(str1, str2, &hints, &ai);
197 log_module(qserver_log, LOG_ERROR, "Unable to find address [%s]:%s: %s", str1 ? str1 : "", str2, gai_strerror(res));
198 } else if (!(qserver_listener = ioset_listen(ai->ai_addr, ai->ai_addrlen, NULL, qserver_accept))) {
199 log_module(qserver_log, LOG_ERROR, "Unable to listen on [%s]:%s", str1 ? str1 : "", str2);
201 conf.password = database_get_data(node, "password", RECDB_QSTRING);
206 qserver_cleanup(void)
210 ioset_close(qserver_listener, 1);
211 for (ii = 0; ii < qserver_nbots; ++ii)
212 if (qserver_clients[ii])
213 DelUser(qserver_clients[ii]->user, NULL, 0, "module finalizing");
214 dict_delete(qserver_dict);
220 qserver_log = log_register_type("QServer", "file:qserver.log");
221 conf_register_reload(qserver_conf_read);
222 qserver_dict = dict_new();
223 reg_exit_func(qserver_cleanup);
228 qserver_finalize(void)