1 /* Direct Query Server module for srvx 1.x
2 * Copyright 2006 Michael Poole <mdpoole@troilus.org>
4 * This is PROPRIETARY, UNPUBLISHED code.
6 * This file is not part of srvx. The only logical reason for you to have
7 * this file is to be working for GameSurge.
9 * If this is not the case, you should delete this copy and inform
10 * Michael Poole <mdpoole@troilus.org> where you acquired it.
12 * The copyright notice above is not evidence that this code is, has been,
13 * or ever will be publicly licensed.
23 const char *qserver_module_deps[] = { NULL };
25 struct qserverClient {
26 struct userNode *user;
29 unsigned int password_ok : 1;
32 static struct log_type *qserver_log;
33 static struct io_fd *qserver_listener;
34 static struct qserverClient **qserver_clients;
35 static dict_t qserver_dict;
36 static unsigned int qserver_nbots;
43 qserver_privmsg(struct userNode *user, struct userNode *target, const char *text, UNUSED_ARG(int server_qualified))
45 struct qserverClient *client;
47 client = dict_find(qserver_dict, target->nick, NULL);
48 assert(client->user == target);
49 ioset_printf(client->fd, "%s P :%s\n", user->nick, text);
53 qserver_notice(struct userNode *user, struct userNode *target, const char *text, UNUSED_ARG(int server_qualified))
55 struct qserverClient *client;
57 client = dict_find(qserver_dict, target->nick, NULL);
58 assert(client->user == target);
59 ioset_printf(client->fd, "%s N :%s\n", user->nick, text);
63 qserver_readable(struct io_fd *fd)
65 struct qserverClient *client;
66 struct service *service;
67 char *argv[MAXNUMPARAMS];
74 assert(client->fd == fd);
75 res = ioset_line_read(fd, tmpline, sizeof(tmpline));
82 len = strlen(tmpline);
83 while (tmpline[len - 1] == '\r' || tmpline[len - 1] == '\n')
84 tmpline[--len] = '\0';
85 argc = split_line(tmpline, false, ArrayLength(argv), argv);
87 ioset_printf(fd, "MISSING_ARGS");
90 if (!strcmp(argv[1], "PASS")
92 && !strcmp(argv[2], conf.password)) {
93 client->password_ok = 1;
94 } else if ((client->password_ok || !conf.password)
95 && (service = service_find(argv[1])) != NULL) {
96 ioset_printf(fd, "%s S\n", argv[0]);
97 svccmd_invoke_argv(client->user, service, NULL, argc - 2, argv + 2, 1);
98 ioset_printf(fd, "%s E\n", argv[0]);
100 ioset_printf(fd, "%s X %s\n", argv[0], argv[1]);
105 qserver_destroy_fd(struct io_fd *fd)
107 struct qserverClient *client;
110 assert(client->fd == fd);
111 dict_remove(qserver_dict, client->user->nick);
112 DelUser(client->user, NULL, 0, "client disconnected");
113 qserver_clients[client->id] = NULL;
118 qserver_accept(UNUSED_ARG(struct io_fd *listener), struct io_fd *fd)
120 struct qserverClient *client;
121 struct sockaddr_storage ss;
126 char nick[NICKLEN+1];
127 char host[HOSTLEN+1];
130 client = calloc(1, sizeof(*client));
134 fd->readable_cb = qserver_readable;
135 fd->destroy_cb = qserver_destroy_fd;
137 for (ii = 0; ii < qserver_nbots; ++ii)
138 if (qserver_clients[ii] == NULL)
140 if (ii == qserver_nbots) {
142 qserver_clients = realloc(qserver_clients, qserver_nbots * sizeof(qserver_clients[0]));
143 for (jj = ii; jj < qserver_nbots; ++jj)
144 qserver_clients[jj] = NULL;
148 qserver_clients[client->id] = client;
149 snprintf(nick, sizeof(nick), " QServ%04d", client->id);
150 safestrncpy(host, "srvx.dummy.user", sizeof(host));
151 safestrncpy(ip, "0.0.0.0", sizeof(ip));
153 res = getpeername(fd->fd, (struct sockaddr*)&ss, &sa_len);
155 getnameinfo((struct sockaddr*)&ss, sa_len, ip, sizeof(host), NULL, 0, NI_NUMERICHOST);
156 if (getnameinfo((struct sockaddr*)&ss, sa_len, host, sizeof(host), NULL, 0, 0) != 0)
157 safestrncpy(host, ip, sizeof(host));
159 client->user = AddLocalUser(nick, nick+1, host, "qserver dummy user", "*+i");
160 irc_pton(&client->user->ip, NULL, ip);
161 dict_insert(qserver_dict, client->user->nick, client);
163 reg_privmsg_func(client->user, qserver_privmsg);
164 reg_notice_func(client->user, qserver_notice);
168 qserver_conf_read(void)
170 struct addrinfo hints;
177 ioset_close(qserver_listener, 1);
178 qserver_listener = NULL;
179 node = conf_get_data("modules/qserver", RECDB_OBJECT);
182 str1 = database_get_data(node, "address", RECDB_QSTRING);
183 str2 = database_get_data(node, "port", RECDB_QSTRING);
186 memset(&hints, 0, sizeof(hints));
187 hints.ai_flags = AI_PASSIVE;
188 hints.ai_socktype = SOCK_STREAM;
189 res = getaddrinfo(str1, str2, &hints, &ai);
191 log_module(qserver_log, LOG_ERROR, "Unable to find address [%s]:%s: %s", str1 ? str1 : "", str2, gai_strerror(res));
192 } else if (!(qserver_listener = ioset_listen(ai->ai_addr, ai->ai_addrlen, NULL, qserver_accept))) {
193 log_module(qserver_log, LOG_ERROR, "Unable to listen on [%s]:%s", str1 ? str1 : "", str2);
195 conf.password = database_get_data(node, "password", RECDB_QSTRING);
200 qserver_cleanup(void)
204 for (ii = 0; ii < qserver_nbots; ++ii)
205 if (qserver_clients[ii])
206 DelUser(qserver_clients[ii]->user, NULL, 0, "module finalizing");
207 dict_delete(qserver_dict);
213 qserver_log = log_register_type("QServer", "file:qserver.log");
214 conf_register_reload(qserver_conf_read);
215 qserver_dict = dict_new();
216 reg_exit_func(qserver_cleanup);
221 qserver_finalize(void)