]> jfr.im git - irc/quakenet/newserv.git/commitdiff
merge
authorPaul <redacted>
Fri, 30 May 2008 19:03:11 +0000 (20:03 +0100)
committerPaul <redacted>
Fri, 30 May 2008 19:03:11 +0000 (20:03 +0100)
14 files changed:
.hgignore
core/error.c
core/error.h
core/main.c
graphing/Makefile.in [new file with mode: 0644]
graphing/dump.c [new file with mode: 0644]
graphing/fsample.c [new file with mode: 0644]
graphing/fsample.h [new file with mode: 0644]
graphing/graphing.c [new file with mode: 0644]
graphing/graphing.h [new file with mode: 0644]
graphing/nterfacer_graphing.c [new file with mode: 0644]
nterfacer/nterfacer.h
regexgline/regexgline.c
regexgline/regexgline.h

index 1b81bfc541f328ae1a5aead411d9a05ffad6c6eb..c7b8b009dfdffc5a9f04e2c560a431e1e9165b13 100644 (file)
--- a/.hgignore
+++ b/.hgignore
@@ -25,3 +25,4 @@ chanserv/*/commandlist.c
 configure.ac.local
 config.h
 settings.mk
+graphing/dump
index 895e786c7b17fdce756b702f6013ae0a29cbc29e..5e4e02c2b25f3e9c2b1524bc8eb41b395f0860d0 100644 (file)
@@ -9,6 +9,8 @@
 
 FILE *logfile;
 
+static corehandler *coreh, *coret;
+
 char *sevtostring(int severity) {
   switch(severity) {
     case ERR_DEBUG:
@@ -78,3 +80,44 @@ void Error(char *source, int severity, char *reason, ... ) {
     exit(0);
   }
 }
+
+void handlecore(void) { 
+  corehandler *n;
+
+  /* no attempt is made to clean these up */
+  for(n=coreh;coreh;n=coreh->next)
+    (n->fn)(n->arg);
+}
+
+corehandler *registercorehandler(CoreHandlerFn fn, void *arg) {
+  corehandler *c = (corehandler *)malloc(sizeof(corehandler));
+  /* core if we can't allocate!! */
+
+  c->fn = fn;
+  c->arg = arg;
+  c->next = NULL;
+  c->prev = coret;
+  coret = c->prev;
+
+  if(!coreh)
+    coreh = c;
+
+  return c;
+}
+
+void deregistercorehandler(corehandler *c) {
+  if(!c->prev) {
+    coreh = c->next;
+  } else {
+    c->prev->next = c->next;
+  }
+
+  if(!c->next) {
+    coret = c->prev;
+  } else {
+    c->next->prev = c->prev;
+  }
+
+  free(c);
+}
+
index 030c1bbdf747e8ee2a7921849dfe50160e8cf50f..1d76fa6a2884ba0c2e07186e08149cbfe970e474 100644 (file)
@@ -47,6 +47,17 @@ struct error_event {
   char *source;
 };
 
+typedef void (*CoreHandlerFn)(void *arg);
+
+typedef struct corehandler {
+  void *arg;
+  CoreHandlerFn fn;
+  struct corehandler *prev, *next;
+} corehandler;
+
 void Error(char *source, int severity, char *reason, ... );
 
+corehandler *registercorehandler(CoreHandlerFn fn, void *arg);
+void deregistercorehandler(corehandler *c);
+
 #endif
index 4fea98128d90aa567f2a586bf78436d276d300b8..5dfcf27c33478c7dd4ba410c1cb434c5c3889b09 100644 (file)
@@ -20,6 +20,10 @@ void initseed();
 void init_logfile();
 void siginthandler(int sig);
 void sigusr1handler(int sig);
+void sigsegvhandler(int sig);
+void handlecore(void);
+
+static void (*oldsegv)(int);
 
 int main(int argc, char **argv) {
   initseed();
@@ -41,6 +45,7 @@ int main(int argc, char **argv) {
   initmodules();
   signal(SIGINT, siginthandler);
   signal(SIGUSR1, sigusr1handler);
+  oldsegv = signal(SIGSEGV, sigsegvhandler);
 
   /* Main loop */
   for(;;) {
@@ -81,3 +86,10 @@ void siginthandler(int sig) {
 void sigusr1handler(int sig) {
   newserv_sigusr1_pending = 1;
 }
+
+void sigsegvhandler(int sig) {
+  handlecore();
+
+  oldsegv(sig);
+}
+
diff --git a/graphing/Makefile.in b/graphing/Makefile.in
new file mode 100644 (file)
index 0000000..3add014
--- /dev/null
@@ -0,0 +1,11 @@
+@include@ @includel@../build.mk@includel@
+
+.PHONY: all
+all: graphing.so nterfacer_graphing.so dump
+
+graphing.so: graphing.o fsample.o
+
+nterfacer_graphing.so: nterfacer_graphing.o
+
+dump: dump.o fsample.o
+       $(CC) $(CFLAGS) -o $@ @srcs@
diff --git a/graphing/dump.c b/graphing/dump.c
new file mode 100644 (file)
index 0000000..2527de9
--- /dev/null
@@ -0,0 +1,55 @@
+#include "graphing.h"
+#include <stdio.h>
+#include <time.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+int dump(fsample_m *f, fsample_t start, fsample_t stop) {
+  int i, j;
+
+  for(i=start;i<stop;i++) {
+    printf("%2d ", i);
+    for(j=0;j<f->pos;j++) {
+      fsample_t t;
+      int moo = fsget_m(f, j, i, &t);
+
+      if(!moo) {
+        int moo2 = fsget_mr(f, j, i, &t);
+        printf("X%2d(%2d) ", t, moo2);
+      } else {
+        printf(" %2d(%2d) ", t, moo);
+      }
+    }
+    printf("\n");
+  }
+
+  return 0;
+}
+
+
+int main(int cargc, char **cargv) {
+  fsample_m *f;
+  int stop = time(NULL) / GRAPHING_RESOLUTION;
+  struct stat sb;
+
+  if(cargc < 2) {
+    puts("insufficient args");
+    return 1;
+  }
+
+  if(stat(cargv[1], &sb) == -1) {
+    puts("file doesn't exist");
+    return 2;
+  }
+
+  f = fsopen_m(0, cargv[1], SAMPLES, NULL, NULL);
+  if(!f)
+    return 3;
+
+  dump(f, stop - 100, stop);
+
+  fsclose_m(f);
+
+  return 0;
+}
+
diff --git a/graphing/fsample.c b/graphing/fsample.c
new file mode 100644 (file)
index 0000000..7744eef
--- /dev/null
@@ -0,0 +1,286 @@
+#include "fsample.h"
+
+#include <sys/types.h>
+#include <sys/uio.h>
+#include <unistd.h>
+#include <sys/mman.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <string.h>
+
+struct fsample_p {
+  fsample_t v;
+  unsigned char iteration;
+};
+
+struct fsample_header {
+  char magic[4];
+  fsample_t version;
+  unsigned char iteration;
+  fsample_t lastpos;
+};
+
+struct fsample {
+  struct fsample_p *m;
+  int fd;
+  size_t samples, len;
+  struct fsample_header *header;
+  void *corehandler;
+  CoreHandlerDelFn corehandlerdel;
+};
+
+static fsample_t version = 1;
+
+static void fscorefree(void *arg) {
+  fsample *f = (fsample *)arg;
+  munmap(f->header, f->len);
+}
+
+fsample *fsopen(char *filename, size_t samples, CoreHandlerAddFn chafn, CoreHandlerDelFn chdfn) {
+  int flags = 0;
+  int new = 0;
+  fsample *f = (fsample *)malloc(sizeof(fsample));
+  if(!f)
+    return NULL;
+
+  f->len = samples * sizeof(struct fsample_p) + sizeof(struct fsample_header);
+  f->fd = open(filename, O_RDWR|O_CREAT, 0600);
+
+  if(!lseek(f->fd, 0, SEEK_END))
+    new = 1;
+
+  if((f->fd == -1) || (lseek(f->fd, f->len - 1, SEEK_SET) == -1)) {
+    free(f);
+    return NULL;
+  }
+  write(f->fd, "", 1);
+
+  flags = MAP_SHARED;
+#ifdef MAP_NOCORE
+  flags|=MAP_NOCORE;
+#endif
+
+  f->header = mmap(NULL, f->len, PROT_READ|PROT_WRITE, flags, f->fd, 0);
+  if(f->header == MAP_FAILED) {
+    close(f->fd);
+    free(f);
+    return NULL;
+  }
+
+  if(!new && (memcmp(f->header->magic, "FSAMP", sizeof(f->header->magic)) || (version != f->header->version))) {
+    munmap(f->header, f->len);
+    close(f->fd);
+    free(f);
+    return NULL;
+  }
+
+  if(chafn && chdfn) {
+    f->corehandler = chafn(fscorefree, f);
+    f->corehandlerdel = chdfn;
+  } else {
+    f->corehandler = NULL;
+    f->corehandlerdel = NULL;
+  }
+
+  memcpy(f->header->magic, "FSAMP", sizeof(f->header->magic));
+  f->header->version = version;
+
+  f->m = (struct fsample_p *)(f->header + 1);
+  f->samples = samples;
+
+  if(f->header->iteration == 0)
+    f->header->iteration = 1;
+
+  return f;
+}
+
+void fsclose(fsample *f) {
+  munmap(f->header, f->len);
+  close(f->fd);
+
+  if(f->corehandlerdel && f->corehandler)
+    (f->corehandlerdel)(f->corehandler);
+
+  free(f);
+}
+
+static inline unsigned char previteration(fsample *f) {
+  unsigned char p = f->header->iteration - 1;
+  if(p == 0)
+    p = 255;
+  return p;
+}
+
+/* doesn't support writing to negative numbers... */
+inline void fsset(fsample *f, fsample_t pos, fsample_t value) {
+  fsample_t actualpos = pos % f->samples;
+  struct fsample_p *p = &f->m[actualpos];
+
+  if(f->header->lastpos > actualpos) {
+    f->header->iteration++;
+    if(f->header->iteration == 0)
+      f->header->iteration = 1;
+  }
+
+  f->header->lastpos = actualpos;
+
+  p->iteration = f->header->iteration;
+  p->v = value;
+}
+
+static inline fsample_t mmod(int x, int y) {
+#if -5 % 3 == -2
+  int v = x % y;
+  if(v < 0)
+    v = v + y;
+  return v;
+#else
+#error Unknown modulo operator function.
+#endif
+}
+
+/* API functions only have access to positive indicies */
+inline fsample_t __fsget(fsample *f, int pos, fsample_t *t) {
+  struct fsample_p *p = &f->m[mmod(pos, f->samples)];
+  
+  if(p->iteration != f->header->iteration) {
+    unsigned char prev = previteration(f);
+
+    if(prev != p->iteration || (pos <= f->header->lastpos)) {
+      /*printf("bad: prev: %d p->iteration: %d, pos: %d lastpos: %d\n", prev, p->iteration, pos, f->header->lastpos);*/
+      return 0;
+    }
+  }
+
+  *t = p->v;
+  return p->iteration;
+}
+
+inline fsample_t fsget_r(fsample *f, fsample_t pos, fsample_t *t) {
+  struct fsample_p *p = &f->m[mmod(pos, f->samples)];
+
+  *t = p->v;
+  return p->iteration;
+}
+
+inline fsample_t fsget(fsample *f, fsample_t pos, fsample_t *t) {
+  return __fsget(f, pos, t);
+}
+
+int fsadd_m(fsample_m *f, char *filename, size_t freq, DeriveValueFn derive, void *tag) {
+  fsample_m_entry *p = &f->entry[f->pos];
+
+  p->f = fsopen(filename, f->samples / freq, f->chafn, f->chdfn);
+  if(!p->f)
+    return 0;
+
+  p->freq = freq;
+  p->derive = derive;
+  p->tag = tag;
+  f->pos++;
+  return 1;
+}
+
+fsample_m *fsopen_m(size_t count, char *filename, size_t samples, CoreHandlerAddFn chafn, CoreHandlerDelFn chdfn) {
+  fsample_m *n = (fsample_m *)malloc(sizeof(fsample_m) + (count + 1) * sizeof(fsample_m_entry));
+  if(!n)
+    return NULL;
+
+  n->samples = samples;
+  n->pos = 0;
+  n->chafn = chafn;
+  n->chdfn = chdfn;
+
+  if(!fsadd_m(n, filename, 1, NULL, 0)) {
+    free(n);
+    return NULL;
+  }
+
+  return n;
+}
+
+void fsset_m(fsample_m *f, fsample_t pos, fsample_t value) {
+  int i;
+
+  for(i=0;i<f->pos;i++) {
+    fsample_t v;
+
+    if((pos + 1) % f->entry[i].freq != 0)
+      continue;
+
+    if(f->entry[i].derive) {
+      v = (f->entry[i].derive)(f, i, pos, f->entry[i].tag);
+    } else {
+      v = value;
+    }
+
+    fsset(f->entry[i].f, pos / f->entry[i].freq, v);
+  }
+}
+
+void fsclose_m(fsample_m *f) {
+  int i;
+
+  for(i=0;i<f->pos;i++)
+    fsclose(f->entry[i].f);
+  free(f);
+}
+
+inline fsample_t __fsget_m(fsample_m *f, int entry, int pos, fsample_t *t) {
+  return __fsget(f->entry[entry].f, pos / f->entry[entry].freq, t);
+}
+
+inline fsample_t fsget_m(fsample_m *f, int entry, fsample_t pos, fsample_t *t) {
+  return fsget(f->entry[entry].f, pos / f->entry[entry].freq, t);
+}
+
+inline fsample_t fsget_mr(fsample_m *f, int entry, fsample_t pos, fsample_t *t) {
+  return fsget_r(f->entry[entry].f, pos / f->entry[entry].freq, t);
+}
+
+fsample_t fsamean(fsample_m *f, int entry, fsample_t pos, void *tag) {
+  fsample_t c = 0;
+  long samples = (long)tag;
+  int count = 0;
+  int rpos = pos / f->entry[0].freq;
+  int i;
+  fsample_t t;
+
+  for(i=0;i<samples;i++) {
+    if(__fsget_m(f, 0, rpos - i, &t)) {
+      c+=t;
+      count++;
+    } else {
+/*      printf("bad :(\n");*/
+    }
+  }
+
+  if(count == 0)
+    return 0;
+
+  return c / count;
+}
+
+fsample_t fsapmean(fsample_m *f, int entry, fsample_t pos, void *tag) {
+  fsample_t c = 0;
+  long samples = (long)tag;
+  int count = 0;
+  int rpos = pos / f->entry[entry - 1].freq;
+  int i;
+  fsample_t t;
+
+  for(i=0;i<=samples;i++) {
+    if(__fsget(f->entry[entry - 1].f, rpos - i, &t)) {
+      c+=t;
+      count++;
+    } else {
+      /*printf("bad :(\n");*/
+    }
+  }
+
+  if(count == 0)
+    return 0;
+
+  return c / count;
+}
diff --git a/graphing/fsample.h b/graphing/fsample.h
new file mode 100644 (file)
index 0000000..74fc421
--- /dev/null
@@ -0,0 +1,50 @@
+#ifndef __FSAMPLE_H
+#define __FSAMPLE_H
+
+#include <sys/types.h>
+
+typedef u_int32_t fsample_t;
+
+typedef struct fsample fsample;
+
+/* nice loss of type safety here... */
+typedef void *(*CoreHandlerAddFn)(void *handler, void *arg);
+typedef void (*CoreHandlerDelFn)(void *);
+
+/* single sample functions */
+fsample *fsopen(char *filename, size_t samples, CoreHandlerAddFn chafn, CoreHandlerDelFn chdfn);
+void fsclose(fsample *f);
+inline void fsset(fsample *f, fsample_t pos, fsample_t value);
+inline fsample_t fsget(fsample *f, fsample_t pos, fsample_t *t);
+inline fsample_t fsget_r(fsample *f, fsample_t pos, fsample_t *t);
+
+struct fsample_m;
+typedef fsample_t (*DeriveValueFn)(struct fsample_m *v, int entry, fsample_t pos, void *tag);
+
+typedef struct fsample_m_entry {
+  size_t freq;
+  fsample *f;
+  void *tag;
+  DeriveValueFn derive;
+} fsample_m_entry;
+
+typedef struct fsample_m {
+  size_t pos, samples;
+  CoreHandlerAddFn chafn;
+  CoreHandlerDelFn chdfn;
+  struct fsample_m_entry entry[];
+} fsample_m;
+
+/* multiple sample functions */
+fsample_m *fsopen_m(size_t count, char *filename, size_t samples, CoreHandlerAddFn chafn, CoreHandlerDelFn chdfn);
+void fsclose_m(fsample_m *f);
+int fsadd_m(fsample_m *f, char *filename, size_t freq, DeriveValueFn derive, void *tag);
+void fsset_m(fsample_m *f, fsample_t pos, fsample_t value);
+inline fsample_t fsget_m(fsample_m *f, int entry, fsample_t pos, fsample_t *t);
+inline fsample_t fsget_mr(fsample_m *f, int entry, fsample_t pos, fsample_t *t);
+
+/* aggregates */
+fsample_t fsamean(fsample_m *f, int entry, fsample_t pos, void *tag);
+fsample_t fsapmean(fsample_m *f, int entry, fsample_t pos, void *tag);
+
+#endif
diff --git a/graphing/graphing.c b/graphing/graphing.c
new file mode 100644 (file)
index 0000000..5a8cfed
--- /dev/null
@@ -0,0 +1,161 @@
+#include <string.h>
+#include <stdio.h>
+
+#include "../core/hooks.h"
+#include "../core/config.h"
+#include "../usercount/usercount.h"
+#include "../lib/sstring.h"
+#include "../core/schedule.h"
+#include "../core/error.h"
+#include "../lib/sha1.h"
+#include "../lib/hmac.h"
+
+#include "graphing.h"
+
+static void gr_newserver(int hook, void *arg);
+static void gr_lostserver(int hook, void *arg);
+static void tick(void *arg);
+static void openserver(int servernum);
+static void closeserver(int servernum);
+
+fsample_m *servergraphs[MAXSERVERS];
+static void *sched;
+
+static sstring *path;
+
+void _init(void) {
+  int i;
+
+  memset(servergraphs, 0, sizeof(servergraphs));
+
+  path = getcopyconfigitem("graphing", "path", "", 100);
+  if(!path || !path->content || !path->content[0]) {
+    Error("graphing", ERR_WARNING, "Path not set, not loaded.");
+    return;
+  }
+
+  for(i=0;i<MAXSERVERS;i++)
+    openserver(i);
+
+  registerhook(HOOK_SERVER_NEWSERVER, gr_newserver);
+  registerhook(HOOK_SERVER_LOSTSERVER, gr_lostserver);
+
+  sched = schedulerecurring(time(NULL), 0, 1, tick, NULL);
+}
+
+void _fini(void) {
+  int i;
+  if(sched)
+    deleteschedule(sched, tick, NULL);
+
+  for(i=0;i<MAXSERVERS;i++)
+    if(servermonitored(i))
+      closeserver(i);
+
+  freesstring(path);
+
+  deregisterhook(HOOK_SERVER_NEWSERVER, gr_newserver);
+  deregisterhook(HOOK_SERVER_LOSTSERVER, gr_lostserver);
+}
+
+int servermonitored(int servernum) {
+  return servergraphs[servernum] != NULL;
+}
+
+static char *appendsuffix(char *prefix, char *suffix) {
+  static char buf[1024];
+
+  snprintf(buf, sizeof(buf), "%s%s", prefix, suffix);
+
+  return buf;
+}
+
+static void openserver(int servernum) {
+  unsigned char digest[SHA1_DIGESTSIZE];
+  char filename[512], hexdigest[sizeof(digest)*2 + 1];
+  FILE *f;
+  SHA1_CTX sha;
+  fsample_m *m;
+
+  if(servermonitored(servernum))
+    return;
+
+  if(serverlist[servernum].linkstate == LS_INVALID)
+    return;
+
+  SHA1Init(&sha);
+  SHA1Update(&sha, (unsigned char *)serverlist[servernum].name->content, serverlist[servernum].name->length);
+  SHA1Final(digest, &sha);
+
+  snprintf(filename, sizeof(filename), "%s/%s", path->content, hmac_printhex(digest, hexdigest, sizeof(digest)));
+
+  f = fopen(appendsuffix(filename, ".name"), "w");
+  if(!f) {
+    Error("graphing", ERR_WARNING, "Unable to create name file for %s (%s.name)", serverlist[servernum].name->content, filename);
+    return;
+  }
+
+  fprintf(f, "%s\n", serverlist[servernum].name->content);
+  fclose(f);
+
+  /* 0: seconds
+     1: minutes
+     2: hours
+     3: days
+     4: weeks
+     5: months
+   */
+
+  m = fsopen_m(GRAPHING_DATASETS, appendsuffix(filename, ".0"), SAMPLES, (CoreHandlerAddFn)registercorehandler, (CoreHandlerDelFn)deregistercorehandler);
+  if(!m) {
+    Error("graphing", ERR_WARNING, "Unable to create main backing store for %s (%s.0)", serverlist[servernum].name->content, filename);
+    return;
+  }
+/*
+  if(!fsadd_m(m, appendsuffix(filename, ".1"), PERMINUTE, fsapmean, (void *)PERMINUTE) ||
+     !fsadd_m(m, appendsuffix(filename, ".2"), PERMINUTE * 24, fsapmean, (void *)(PERMINUTE * 24)) ||
+     !fsadd_m(m, appendsuffix(filename, ".3"), PERMINUTE * 24 * 7, fsapmean, (void *)(PERMINUTE * 24 * 7)) ||
+     !fsadd_m(m, appendsuffix(filename, ".4"), PERMINUTE * 24 * 7 * 4, fsapmean, (void *)(PERMINUTE * 24 * 7 * 4)) ||
+     !fsadd_m(m, appendsuffix(filename, ".5"), PERMINUTE * 24 * 7 * 4 * 12, fsapmean, (void *)(PERMINUTE * 24 * 7 * 4 * 12)))
+  {
+    Error("graphing", ERR_WARNING, "Unable to create main side store for %s (%s.X)", serverlist[servernum].name->content, filename);
+    fsclose_m(m);
+    return;
+  }
+*/
+  servergraphs[servernum] = m;
+}
+
+static void closeserver(int servernum) {
+  if(!servermonitored(servernum))
+    return;
+
+  fsclose_m(servergraphs[servernum]);
+  servergraphs[servernum] = NULL;
+}
+
+static void gr_newserver(int hook, void *arg) {
+  long num = (long)arg;
+
+  openserver(num);
+}
+
+static void gr_lostserver(int hook, void *arg) {
+  long num = (long)arg;
+
+  closeserver(num);
+}
+
+static void tick(void *arg) {
+  time_t t = time(NULL);
+  int i;
+
+  if(t % GRAPHING_RESOLUTION != 0)
+    return;
+
+  for(i=0;i<MAXSERVERS;i++)
+    if(servermonitored(i))
+      fsset_m(servergraphs[i], t / GRAPHING_RESOLUTION, servercount[i]);
+}
+
+
diff --git a/graphing/graphing.h b/graphing/graphing.h
new file mode 100644 (file)
index 0000000..7c507af
--- /dev/null
@@ -0,0 +1,16 @@
+#ifndef __GRAPHING_H
+#define __GRAPHING_H
+
+#include "../server/server.h"
+#include "../graphing/fsample.h"
+
+extern fsample_m *servergraphs[MAXSERVERS];
+int servermonitored(int servernum);
+
+#define GRAPHING_DATASETS 5
+#define GRAPHING_RESOLUTION 5
+
+#define PERMINUTE (60 / GRAPHING_RESOLUTION)
+#define SAMPLES PERMINUTE * 60 * 24 * 7 * 4 * 12
+
+#endif
diff --git a/graphing/nterfacer_graphing.c b/graphing/nterfacer_graphing.c
new file mode 100644 (file)
index 0000000..910202d
--- /dev/null
@@ -0,0 +1,73 @@
+#include "../nterfacer/library.h"
+#include "../nterfacer/nterfacer.h"
+
+#include "graphing.h"
+
+#include <time.h>
+
+#define ERR_SERVER_NOT_MONITORED        0x01
+#define ERR_BAD_PARAMETERS              0x02
+#define ERR_BAD_ENTRY                   0x03
+
+int handle_servernames(struct rline *li, int argc, char **argv);
+int handle_serverdata(struct rline *li, int argc, char **argv);
+
+static struct service_node *g_node;
+
+void _init(void) {
+  g_node = register_service("graphing");
+  if(!g_node)
+    return;
+
+  register_handler(g_node, "servernames", 0, handle_servernames);
+  register_handler(g_node, "serverdata", 3, handle_serverdata);
+}
+
+void _fini(void) {
+  if(g_node)
+    deregister_service(g_node);
+}
+
+int handle_servernames(struct rline *li, int argc, char **argv) {
+  int i;
+
+  for(i=0;i<MAXSERVERS;i++) {
+    if((serverlist[i].linkstate != LS_INVALID) && servermonitored(i)) {
+      if(ri_append(li, "%d:%s", i, serverlist[i].name->content) == BF_OVER)
+        return ri_error(li, BF_OVER, "Buffer overflow");
+    }
+  }
+
+  return ri_final(li);
+}
+
+int handle_serverdata(struct rline *li, int argc, char **argv) {
+  int servernum = atoi(argv[0]);
+  unsigned int entry = atoi(argv[1]);
+  fsample_t count = atoi(argv[2]);
+  time_t t = time(NULL) / GRAPHING_RESOLUTION;
+  int i, ret;
+  fsample_m *m;
+
+  if(!servermonitored(servernum))
+    return ri_error(li, ERR_SERVER_NOT_MONITORED, "Server not monitored");
+
+  m = servergraphs[servernum];
+
+  if(entry > m->pos) /* not inclusive as 0 is used for for the base index */
+    return ri_error(li, ERR_BAD_PARAMETERS, "Bad parameters");
+
+  for(i=0;i<count;i++) {
+    fsample_t v;
+    if(fsget_m(m, entry, t - m->entry[entry].freq * i, &v)) {
+      ret = ri_append(li, "%d", v);
+    } else {
+      ret = ri_append(li, "-1", v);
+    }
+    if(ret == BF_OVER)
+      return ri_error(li, BF_OVER, "Buffer overflow");
+  }
+
+  return ri_final(li);
+}
+
index 93db79d109382f59fcd95ffdf9672636a5e712ac..fa2fdf258fb063f1a2f3555ccfd4e7907253b05b 100644 (file)
@@ -9,6 +9,8 @@
 #include <sys/types.h>
 #include <netinet/in.h>
 
+#include "../lib/sstring.h"
+
 #include "esockets.h"
 #include "library.h"
 
index 6f1e0f8ade07be39d707e74c8b2d2b36f1c11d90..f138207a2c60e86ca27060a26409947d50db210e 100644 (file)
@@ -244,7 +244,7 @@ void rg_dodelay(void *arg) {
     }
   }
   
-  irc_send("%s GL * +%s %d :AUTO: %s (ID: %08lx)\r\n", mynumeric->content, hostname, rg_expiry_time, delay->reason->reason->content, delay->reason->glineid);
+  irc_send("%s GL * +%s %d %d :AUTO: %s (ID: %08lx)\r\n", mynumeric->content, hostname, rg_expiry_time, time(NULL), delay->reason->reason->content, delay->reason->glineid);
   rg_deletedelay(delay);
 }
 
@@ -399,13 +399,18 @@ int rg_gline(void *source, int cargc, char **cargv) {
   rg_sqlescape_string(eereason, cargv[3], strlen(cargv[3]));
   
   rg_sqlquery("INSERT INTO regexglines (gline, setby, reason, expires, type) VALUES ('%s', '%s', '%s', %d, %s)", eemask, eesetby, eereason, realexpiry, cargv[2]);
-  if (!rg_sqlquery("SELECT id FROM regexglines WHERE gline = '%s' AND setby = '%s' AND reason = '%s' AND expires = %d AND type = %s ORDER BY ID DESC LIMIT 1", eemask, eesetby, eereason, realexpiry, cargv[2])) {
+  if (!rg_sqlquery("SELECT LAST_INSERT_ID()")) {
     rg_sqlresult res;
     if((res = rg_sqlstoreresult())) {
       rg_sqlrow row;
       row = rg_sqlgetrow(res);
       if (row) {
-        rp = rg_newsstruct(row[0], cargv[0], np->nick, cargv[3], "", cargv[2], realexpiry, 0);
+        int id = atoi(row[0]);
+        if(id == 0) {
+          rp = NULL;
+        } else {
+          rp = rg_newsstruct(row[0], cargv[0], np->nick, cargv[3], "", cargv[2], realexpiry, 0);
+        }
         rg_sqlfree(res);
         if(!rp) {
           rg_sqlquery("DELETE FROM regexglines WHERE gline = '%s' AND setby = '%s' AND reason = '%s' AND expires = %d AND type = %s ORDER BY ID DESC LIMIT 1", eemask, eesetby, eereason, realexpiry, cargv[2]);
@@ -712,7 +717,7 @@ void rg_sqlescape_string(char *dest, char *source, size_t length) {
   if(length >= RG_QUERY_BUF_SIZE)
     length = RG_QUERY_BUF_SIZE - 1;
 
-  mysql_escape_string(dest, source, length);
+  mysql_real_escape_string(&rg_sql, dest, source, length);
 }
 
 int rg_sqlquery(char *format, ...) {
@@ -968,11 +973,12 @@ int __rg_dogline(struct rg_glinelist *gll, nick *np, struct rg_struct *rp, char
     }
   }
   
-  irc_send("%s GL * +%s %d :AUTO: %s (ID: %08lx)\r\n", mynumeric->content, hostname, rg_expiry_time, rp->reason->content, rp->glineid);
+  irc_send("%s GL * +%s %d %d :AUTO: %s (ID: %08lx)\r\n", mynumeric->content, hostname, rg_expiry_time, time(NULL), rp->reason->content, rp->glineid);
   return usercount;
 }
 
-int floodprotection = 0;
+static int floodprotection = 0;
+static int lastfloodspam = 0;
 
 void rg_dogline(struct rg_glinelist *gll, nick *np, struct rg_struct *rp, char *matched) {
   int t = time(NULL);
@@ -980,11 +986,15 @@ void rg_dogline(struct rg_glinelist *gll, nick *np, struct rg_struct *rp, char *
   if(t > floodprotection) {
     floodprotection = t;
   } else if((floodprotection - t) / 8 > RG_NETWORK_WIDE_MAX_GLINES_PER_8_SEC) {
-    channel *cp = findchannel("#twilightzone");
-    if(cp)
-      controlchanmsg(cp, "WARNING! REGEXGLINE DISABLED FOR AN HOUR DUE TO NETWORK WIDE LOOKING GLINE!");
-    controlwall(NO_OPER, NL_MANAGEMENT, "WARNING! REGEXGLINE DISABLED FOR AN HOUR DUE TO NETWORK WIDE LOOKING GLINE!");
-    floodprotection = t + RG_NETWORK_WIDE_MAX_GLINES_PER_8_SEC * 3600 * 8;
+    if(t > lastfloodspam + 3600) {
+      channel *cp = findchannel("#twilightzone");
+      if(cp)
+        controlchanmsg(cp, "WARNING! REGEXGLINE DISABLED FOR AN HOUR DUE TO NETWORK WIDE LOOKING GLINE!: %d exceeded %d", (floodprotection - t) / 8, RG_NETWORK_WIDE_MAX_GLINES_PER_8_SEC);
+      controlwall(NO_OPER, NL_MANAGEMENT, "WARNING! REGEXGLINE DISABLED FOR AN HOUR DUE TO NETWORK WIDE LOOKING GLINE!");
+      lastfloodspam = t;
+      floodprotection = t + RG_NETWORK_WIDE_MAX_GLINES_PER_8_SEC * 3600 * 8;
+    }
+    return;
   }
 
   floodprotection+=__rg_dogline(gll, np, rp, matched);
index 7ccad1de08e9c3af14b6e2e4df428220ce4f6989..885d8f7f83bcb40b404dbca8bccc1f7af32c7ad9 100644 (file)
@@ -30,7 +30,7 @@
 #define RG_MINIMUM_DELAY_TIME     5
 #define RG_MAXIMUM_RAND_TIME      15
 #define RG_EXPIRY_TIME_DEFAULT    1800
-#define RG_NETWORK_WIDE_MAX_GLINES_PER_8_SEC 625 /* 5000 / 8 */
+#define RG_NETWORK_WIDE_MAX_GLINES_PER_8_SEC 625*8 /* 5000 / 8 */
 
 #define RGStringise(x)            #x
 #define RGBuildHostname(buf, np)  snprintf(buf, sizeof(buf), "%s!%s@%s\r%s", np->nick, np->ident, np->host->name->content, np->realname->name->content);