]> jfr.im git - irc/quakenet/newserv.git/commitdiff
Split xsb into pre ircd (well, pre good ircd) support and post ircd support versions...
authorChris Porter <redacted>
Mon, 13 Oct 2008 01:03:45 +0000 (02:03 +0100)
committerChris Porter <redacted>
Mon, 13 Oct 2008 01:03:45 +0000 (02:03 +0100)
defaults.mk
xsb/Makefile.in
xsb/xsb-postircd.c [moved from xsb/xsb.c with 97% similarity]
xsb/xsb-preircd.c [new file with mode: 0644]

index fa0c91670fbce3d85aedf79c8a4970a98fcaf373..8e7efe235e693e3abc623c01098fb2188ba9ff92 100644 (file)
@@ -5,3 +5,4 @@ USE_VALGRIND=0
 SSTRING_NEW=0
 SSTRING_MMAP=0
 HOOKS_NEW=0
+XSB_ENGINE=pre
index 63476d9b0816485edece5d76e347189aff59187b..ec6fe6793f2b2db267cc75cbf9a8f98666a1f297 100644 (file)
@@ -3,4 +3,4 @@
 .PHONY: all
 all: xsb.so
 
-xsb.so: xsb.o
+xsb.so: xsb-${XSB_ENGINE}ircd.o xsb.o
similarity index 97%
rename from xsb/xsb.c
rename to xsb/xsb-postircd.c
index 2450c415ca0ade1ad95b75be80afe388a9c692f5..503241bea3ec5a20fd1c8f27100ac3351494c4c7 100644 (file)
--- a/xsb/xsb.c
@@ -15,8 +15,6 @@
 #include "../lib/strlfunc.h"
 #include "xsb.h"
 
-#undef XSB_DEBUG
-
 static const char *DEFAULT_SERVICE_MASKS[] = { "services*.*.quakenet.org", (char *)0 };
 
 static array defaultservicemasks_a;
@@ -59,7 +57,7 @@ void _init(void) {
 
   servicemasks = getconfigitems("xsb", "servicemask");
   if(!servicemasks || !servicemasks->cursi)
-    Error("xsb", ERR_WARNING, "No service masks in config file (xsb/servicemask), using defaults");
+    Error("xsb", ERR_WARNING, "No service masks in config file (xsb/servicemask), using defaults.");
 }
 
 void _fini(void) {
@@ -191,9 +189,9 @@ static void xsb_send(const char *format, ...) {
   if(controlnum[0]) {
     directsend(buf);
   } else {
-    struct messagequeue *q = (struct messagequeue *)malloc(sizeof(struct messagequeue) + len);
+    struct messagequeue *q = (struct messagequeue *)malloc(sizeof(struct messagequeue) + len + 5);
     
-    strlcpy(q->buf, buf, len + 1);
+    strlcpy(q->buf, buf, len + 2);
     q->next = NULL;
     if(tail) {
       tail->next = q;
diff --git a/xsb/xsb-preircd.c b/xsb/xsb-preircd.c
new file mode 100644 (file)
index 0000000..de2a84f
--- /dev/null
@@ -0,0 +1,331 @@
+#include <string.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include "../core/hooks.h"
+#include "../lib/splitline.h"
+#include "../core/config.h"
+#include "../irc/irc.h"
+#include "../lib/array.h"
+#include "../lib/base64.h"
+#include "../lib/irc_string.h"
+#include "../core/error.h"
+#include "../localuser/localuser.h"
+#include "../lib/strlfunc.h"
+#include "../lib/sha1.h"
+#include "../irc/irc.h"
+#include "../lib/hmac.h"
+#include "../core/schedule.h"
+#include "xsb.h"
+
+static const char *DEFAULT_SERVICE_MASKS[] = { "services*.*.quakenet.org", (char *)0 };
+
+static array defaultservicemasks_a;
+static sstring **defaultservicemasks;
+
+static void handlemaskprivmsg(int, void *);
+static CommandTree *cmds;
+
+struct messagequeue {
+  struct messagequeue *next;
+  long numeric;
+  char buf[];
+};
+
+struct messagequeue *head, *tail;
+
+static nick *xsbnick;
+static void *xsbnicksched;
+
+static void handler(nick *target, int messagetype, void **args);
+static void flushqueue(void);
+
+static char *servicenick(char *server) {
+  static char nickbuf[NICKLEN+1];
+  char digest[SHA1_DIGESTSIZE*2+1];
+  unsigned char digestbuf[SHA1_DIGESTSIZE];
+  SHA1_CTX s;
+
+  SHA1Init(&s);
+  SHA1Update(&s, (unsigned char *)server, strlen(server));
+  SHA1Final(digestbuf, &s);
+
+  snprintf(nickbuf, sizeof(nickbuf), "XSB1-%s", hmac_printhex(digestbuf, digest, SHA1_DIGESTSIZE));
+
+  return nickbuf;
+}
+
+static void setuplocaluser(void *arg) {
+  xsbnicksched = NULL;
+
+  xsbnick = registerlocaluser(servicenick(myserver->content), "xsb", "xsb.quakenet.org", "eXtended service broadcast localuser (v1)", NULL, UMODE_OPER | UMODE_SERVICE | UMODE_INV, handler);
+  if(!xsbnick) {
+    xsbnicksched = scheduleoneshot(time(NULL)+1, setuplocaluser, NULL);
+  } else {
+    flushqueue();
+  }
+}
+
+void _init(void) {
+  const char **p;
+  array *servicemasks;
+
+  cmds = newcommandtree();
+  if(!cmds)
+    return;
+
+  xsbnicksched = scheduleoneshot(time(NULL)+1, setuplocaluser, NULL);
+  
+  registerhook(HOOK_NICK_MASKPRIVMSG, &handlemaskprivmsg);
+  
+  array_init(&defaultservicemasks_a, sizeof(sstring *));
+
+  for(p=DEFAULT_SERVICE_MASKS;*p;p++) {
+    int i = array_getfreeslot(&defaultservicemasks_a);
+    defaultservicemasks = (sstring **)defaultservicemasks_a.content;
+
+    defaultservicemasks[i] = getsstring(*p, strlen(*p));
+  }
+
+  servicemasks = getconfigitems("xsb", "servicemask");
+  if(!servicemasks || !servicemasks->cursi)
+    Error("xsb", ERR_WARNING, "No service masks in config file (xsb/servicemask), using defaults.");
+}
+
+void _fini(void) {
+  int i;
+  struct messagequeue *q, *nq;
+
+  if(xsbnick)
+    deregisterlocaluser(xsbnick, NULL);
+
+  if(xsbnicksched)
+    deleteschedule(xsbnicksched, setuplocaluser, NULL);
+
+  if(!cmds)
+    return;
+
+  destroycommandtree(cmds);
+
+  deregisterhook(HOOK_NICK_MASKPRIVMSG, &handlemaskprivmsg);
+
+  for(i=0;i<defaultservicemasks_a.cursi;i++)
+    freesstring(defaultservicemasks[i]);
+  array_free(&defaultservicemasks_a);
+
+  for(q=head;q;q=nq) {
+    nq = q->next;
+    free(q);
+  }
+  
+  head = NULL;
+  tail = NULL;
+}
+
+void xsb_addcommand(const char *name, const int maxparams, CommandHandler handler) {
+  addcommandtotree(cmds, name, 0, maxparams, handler);
+}
+
+void xsb_delcommand(const char *name, CommandHandler handler) {
+  deletecommandfromtree(cmds, name, handler);
+}
+
+static void handlemaskprivmsg(int hooknum, void *args) {
+  void **hargs = (void **)args;
+  nick *source = hargs[0];
+  char *message = hargs[2];
+  Command *cmd;
+  int cargc;
+  char *cargv[50];
+  server *s;
+
+  if(!source)
+    return;
+
+  if(!IsOper(source) || !IsService(source))
+    return;
+
+  cargc = splitline(message, cargv, 50, 0);
+  if(cargc < 2)
+    return;
+
+  if(strcmp(cargv[0], "XSB1"))
+    return;
+
+  s = &serverlist[homeserver(source->numeric)];
+  if(s->linkstate != LS_LINKED) {
+    Error("xsb", ERR_WARNING, "Got XSB message from unlinked server (%s): %s", s->name->content, source->nick);
+    return;
+  }
+
+#ifndef XSB_DEBUG
+  if(!(s->flags & SMODE_SERVICE)) {
+    Error("xsb", ERR_WARNING, "Got XSB message from non-service server (%s): %s", s->name->content, source->nick);
+    return;
+  }
+#endif
+
+  cmd = findcommandintree(cmds, cargv[1], 1);
+  if(!cmd)
+    return;
+
+  if(cmd->maxparams < (cargc - 2)) {
+    rejoinline(cargv[cmd->maxparams], cargc - (cmd->maxparams));
+    cargc = (cmd->maxparams) + 2;
+  }
+
+  (cmd->handler)(source, cargc - 2, &cargv[2]);
+}
+
+static void directsend(struct messagequeue *q) {
+  nick *np = getnickbynumeric(q->numeric);
+  if(!np || !IsOper(np) || !IsService(np))
+    return;
+
+#ifndef XSB_DEBUG
+  if(!(serverlist[homeserver(np->numeric)].flags & SMODE_SERVICE))
+    return;
+#endif
+
+  sendmessagetouser(xsbnick, np, "XSB1 %s", q->buf);
+}
+
+static void flushqueue(void) {
+  struct messagequeue *q, *nq;
+    
+  for(q=head;q;q=nq) {
+    nq = q->next;
+
+    directsend(q);
+    free(q);
+  }
+  head = NULL;
+  tail = NULL;
+}
+
+static int getservicemasks(sstring ***masks) {
+  array *aservicemasks = getconfigitems("xsb", "servicemask");
+  if(!aservicemasks || !aservicemasks->cursi)
+    aservicemasks = &defaultservicemasks_a;
+
+  *masks = (sstring **)aservicemasks->content;
+
+  return aservicemasks->cursi;
+}
+
+static void xsb_send(nick *target, const char *format, ...) {
+  char buf[512];
+  va_list va;
+  size_t len;
+  struct messagequeue *q;
+
+  va_start(va, format);
+  len = vsnprintf(buf, sizeof(buf), format, va);
+  va_end(va);
+  if(len >= sizeof(buf))
+    len = sizeof(buf);
+
+  /* sucks */
+  q = (struct messagequeue *)malloc(sizeof(struct messagequeue) + len + 5);
+  q->numeric = target->numeric;
+  strlcpy(q->buf, buf, len + 2);
+
+  if(xsbnick) {
+    directsend(q);
+    free(q);
+  } else {
+    q->next = NULL;
+    if(tail) {
+      tail->next = q;
+    } else {
+      head = q;
+    }
+    tail = q;
+  }
+}
+
+void xsb_broadcast(const char *command, server *service, const char *format, ...) {
+  char buf[512];
+  va_list va;
+  sstring **servicemasks;
+  int i, j;
+  nick *np;
+  unsigned int marker;
+
+  va_start(va, format);
+  vsnprintf(buf, sizeof(buf), format, va);
+  va_end(va);
+
+  if(service) {
+    np = getnickbynick(servicenick(service->name->content));
+    if(!np)
+      return;
+
+    xsb_send(np, "%s %s", command, buf);
+    return;
+  }
+
+  marker = nextservermarker();
+
+  for(i=getservicemasks(&servicemasks)-1;i>=0;i--) {
+    char *mask = servicemasks[i]->content;
+    for(j=0;j<MAXSERVERS;j++) {
+      if(!serverlist[j].name || serverlist[j].marker == marker)
+        continue;
+
+      if(match(mask, serverlist[j].name->content)) {
+        serverlist[j].marker = marker;
+
+        np = getnickbynick(servicenick(serverlist[j].name->content));
+        if(np)
+          xsb_send(np, "%s %s", command, buf);
+      }
+    }
+  }
+}
+
+void xsb_unicast(const char *command, nick *np, const char *format, ...) {
+  char buf[512];
+  va_list va;
+  
+  va_start(va, format);
+  vsnprintf(buf, sizeof(buf), format, va);
+  va_end(va);
+
+  xsb_send(np, "%s %s", command, buf);
+}
+
+int xsb_isservice(server *service) {
+  int i;
+  sstring **servicemasks;
+  char *name = service->name->content;
+
+  if(!(service->flags & SMODE_SERVICE))
+    return 0;
+
+  for(i=getservicemasks(&servicemasks)-1;i>=0;i--)
+    if(match2strings(servicemasks[i]->content, name))
+      return 1;
+
+  return 0;
+}
+
+static void handler(nick *target, int messagetype, void **args) {
+  switch(messagetype) {
+    case LU_PRIVMSG: {
+      void *newargs[3];
+      nick *sender = args[0];
+      char *cargv = args[1];
+
+      newargs[0] = sender;
+      newargs[1] = NULL;
+      newargs[2] = cargv;
+
+      handlemaskprivmsg(0, newargs);
+      break;
+    }
+    case LU_KILLED:
+      xsbnick = NULL;
+      xsbnicksched = scheduleoneshot(time(NULL)+1, setuplocaluser, NULL);
+      break;
+  }
+}