]>
jfr.im git - irc/evilnet/x3.git/blob - src/mod-qserver.c
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 3 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(UNUSED_ARG(void *extra
))
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
, NULL
);
228 qserver_finalize(void)