]> jfr.im git - irc/quakenet/newserv.git/blame - xsb/xsb.c
merge
[irc/quakenet/newserv.git] / xsb / xsb.c
CommitLineData
4c551b15
CP
1/* TODO: catch control messages */
2
2172bfc8
CP
3#include <string.h>
4#include <stdio.h>
5#include <stdarg.h>
6#include "../core/hooks.h"
7#include "../lib/splitline.h"
8#include "../core/config.h"
9#include "../irc/irc.h"
10#include "../lib/array.h"
11#include "../lib/base64.h"
4c551b15 12#include "../lib/irc_string.h"
2172bfc8 13#include "../core/error.h"
4c551b15
CP
14#include "../localuser/localuser.h"
15#include "../lib/strlfunc.h"
2172bfc8
CP
16#include "xsb.h"
17
4c551b15
CP
18#undef XSB_DEBUG
19
2172bfc8 20static const char *DEFAULT_SERVICE_MASKS[] = { "services*.*.quakenet.org", (char *)0 };
4c551b15 21
2172bfc8
CP
22static array defaultservicemasks_a;
23static sstring **defaultservicemasks;
24
25static void handlemaskprivmsg(int, void *);
4c551b15 26static void handlecontrolregistered(int, void *);
2172bfc8
CP
27static CommandTree *cmds;
28
4c551b15
CP
29static char controlnum[6];
30
31struct messagequeue {
32 struct messagequeue *next;
33 char buf[];
34};
35
36struct messagequeue *head, *tail;
2172bfc8
CP
37
38void _init(void) {
39 const char **p;
40 array *servicemasks;
41
4c551b15
CP
42 controlnum[0] = '\0';
43
2172bfc8 44 cmds = newcommandtree();
4c551b15
CP
45 if(!cmds)
46 return;
47
48 registerhook(HOOK_NICK_MASKPRIVMSG, &handlemaskprivmsg);
49 registerhook(HOOK_CONTROL_REGISTERED, &handlecontrolregistered);
50
2172bfc8
CP
51 array_init(&defaultservicemasks_a, sizeof(sstring *));
52
53 for(p=DEFAULT_SERVICE_MASKS;*p;p++) {
54 int i = array_getfreeslot(&defaultservicemasks_a);
55 defaultservicemasks = (sstring **)defaultservicemasks_a.content;
56
57 defaultservicemasks[i] = getsstring(*p, strlen(*p));
58 }
59
60 servicemasks = getconfigitems("xsb", "servicemask");
61 if(!servicemasks || !servicemasks->cursi)
62 Error("xsb", ERR_WARNING, "No service masks in config file (xsb/servicemask), using defaults");
63}
64
65void _fini(void) {
66 int i;
4c551b15
CP
67 struct messagequeue *q, *nq;
68
69 if(!cmds)
70 return;
71
72 destroycommandtree(cmds);
73
74 deregisterhook(HOOK_NICK_MASKPRIVMSG, &handlemaskprivmsg);
75 deregisterhook(HOOK_CONTROL_REGISTERED, &handlecontrolregistered);
2172bfc8
CP
76
77 for(i=0;i<defaultservicemasks_a.cursi;i++)
78 freesstring(defaultservicemasks[i]);
79 array_free(&defaultservicemasks_a);
80
4c551b15
CP
81 for(q=head;q;q=nq) {
82 nq = q->next;
83 free(q);
84 }
85
86 head = NULL;
87 tail = NULL;
88}
2172bfc8 89
4c551b15
CP
90void xsb_addcommand(const char *name, const int maxparams, CommandHandler handler) {
91 addcommandtotree(cmds, name, 0, maxparams, handler);
92}
2172bfc8 93
4c551b15
CP
94void xsb_delcommand(const char *name, CommandHandler handler) {
95 deletecommandfromtree(cmds, name, handler);
2172bfc8
CP
96}
97
98static void handlemaskprivmsg(int hooknum, void *args) {
99 void **hargs = (void **)args;
100 nick *source = hargs[0];
101 char *message = hargs[2];
102 Command *cmd;
103 int cargc;
104 char *cargv[50];
105 server *s;
106
107 if(!source)
108 return;
109
110 if(!IsOper(source) || !IsService(source))
111 return;
112
113 cargc = splitline(message, cargv, 50, 0);
114 if(cargc < 2)
115 return;
116
117 if(strcmp(cargv[0], "XSB1"))
118 return;
119
120 s = &serverlist[homeserver(source->numeric)];
121 if(s->linkstate != LS_LINKED) {
122 Error("xsb", ERR_WARNING, "Got XSB message from unlinked server (%s): %s", s->name->content, source->nick);
123 return;
124 }
125
4c551b15 126#ifndef XSB_DEBUG
2172bfc8
CP
127 if(!(s->flags & SMODE_SERVICE)) {
128 Error("xsb", ERR_WARNING, "Got XSB message from non-service server (%s): %s", s->name->content, source->nick);
129 return;
130 }
131#endif
132
133 cmd = findcommandintree(cmds, cargv[1], 1);
134 if(!cmd)
135 return;
136
137 if(cmd->maxparams < (cargc - 2)) {
138 rejoinline(cargv[cmd->maxparams], cargc - (cmd->maxparams));
139 cargc = (cmd->maxparams) + 2;
140 }
141
142 (cmd->handler)(source, cargc - 2, &cargv[2]);
143}
144
4c551b15
CP
145static void directsend(char *buf) {
146 irc_send("%s P %s", controlnum, buf);
2172bfc8
CP
147}
148
4c551b15
CP
149static void handlecontrolregistered(int hooknum, void *args) {
150 nick *np = (nick *)args;
151
152 if(np) {
153 struct messagequeue *q, *nq;
154
155 longtonumeric2(np->numeric, 5, controlnum);
156
157 for(q=head;q;q=nq) {
158 nq = q->next;
159
160 directsend(q->buf);
161 free(q);
162 }
163 head = NULL;
164 tail = NULL;
165 } else {
166 controlnum[0] = '\0';
167 }
2172bfc8
CP
168}
169
4c551b15
CP
170static int getservicemasks(sstring ***masks) {
171 array *aservicemasks = getconfigitems("xsb", "servicemask");
172 if(!aservicemasks || !aservicemasks->cursi)
173 aservicemasks = &defaultservicemasks_a;
174
175 *masks = (sstring **)aservicemasks->content;
176
177 return aservicemasks->cursi;
178}
179
180static void xsb_send(const char *format, ...) {
181 char buf[512];
182 va_list va;
183 size_t len;
184
185 va_start(va, format);
186 len = vsnprintf(buf, sizeof(buf), format, va);
187 va_end(va);
188 if(len >= sizeof(buf))
189 len = sizeof(buf);
190
191 if(controlnum[0]) {
192 directsend(buf);
193 } else {
194 struct messagequeue *q = (struct messagequeue *)malloc(sizeof(struct messagequeue) + len);
195
196 strlcpy(q->buf, buf, len + 1);
197 q->next = NULL;
198 if(tail) {
199 tail->next = q;
200 } else {
201 head = q;
202 }
203 tail = q;
204 }
205}
206
207void xsb_broadcast(const char *command, server *service, const char *format, ...) {
2172bfc8
CP
208 char buf[512];
209 va_list va;
210 sstring **servicemasks;
2172bfc8 211 int i;
2172bfc8
CP
212
213 va_start(va, format);
214 vsnprintf(buf, sizeof(buf), format, va);
215 va_end(va);
216
4c551b15
CP
217 if(service) {
218 xsb_send("$%s :XSB1 %s %s", service->name->content, command, buf);
219 return;
220 }
2172bfc8 221
4c551b15
CP
222 for(i=getservicemasks(&servicemasks)-1;i>=0;i--)
223 xsb_send("$%s :XSB1 %s %s", servicemasks[i]->content, command, buf);
224}
2172bfc8 225
4c551b15
CP
226void xsb_unicast(const char *command, nick *np, const char *format, ...) {
227 char buf[512];
228 va_list va;
229
230 va_start(va, format);
231 vsnprintf(buf, sizeof(buf), format, va);
232 va_end(va);
2172bfc8 233
4c551b15
CP
234 /* TODO */
235 xsb_send("$%s :XSB1 %s %s", serverlist[homeserver(np->numeric)].name, command, buf);
236 /* xsb_send("%s :XSB1 %s %s", longtonumeric(np->numeric, 5), command, buf);*/
237
2172bfc8 238}
4c551b15
CP
239
240int xsb_isservice(server *service) {
241 int i;
242 sstring **servicemasks;
243 char *name = service->name->content;
244
245 if(!(service->flags & SMODE_SERVICE))
246 return 0;
247
248 for(i=getservicemasks(&servicemasks)-1;i>=0;i--)
249 if(match2strings(servicemasks[i]->content, name))
250 return 1;
251
252 return 0;
253}
254