#include #include #include #include #include "hash.h" #include "client.h" #include "channel.h" #include "hermes.h" #include "msg.h" #include "handler.h" enum { DEBUG = 1, }; u64int myserial; char* myname; Hash* clnthash; Hash* chanhash; Channel* clntchan; static long ioprocsetname(va_list *arg) { char *name = va_arg(*arg, char*); threadsetname(name); return 0; } void dbg(char *fmt, ...) { char prefix[128], msg[512]; int n; va_list arg; va_start(arg, fmt); if(DEBUG){ snprint(prefix, sizeof(prefix), "%d %-20s %08#p: %s\n", getpid(), threadgetname(), getcallerpc(&fmt), fmt); n = vsnprint(msg, sizeof(msg), prefix, arg); write(2, msg, n); } } Client* findnick(char *nick) { Client *c; qlock(clnthash); c = gethash(clnthash, nick); qunlock(clnthash); return c; } IrcChannel* findchannel(char *chan) { IrcChannel *ch; qlock(chanhash); ch = gethash(chanhash, chan); qunlock(chanhash); return ch; } void clientthread(void *v) { char *p, *rest, buf[1024]; int n, l; Client *c; Msg *m; n = 0; c = v; threadsetname("dingus %s", c->info->raddr); sprint(buf, "slave %s", c->info->raddr); iocall(c->io, ioprocsetname, buf); memset(buf, 0, sizeof(buf)); l = 0; for(;;){ if(l >= sizeof(buf)-1){ fprint(2, "too chatty\n"); break; } n = ioread(c->io, c->data, buf+l, sizeof(buf)-l-1); if(n <= 0) break; buf[l+n] = 0; //fprint(2, "ioread '%s'\n", buf+l); more: if((p = findmsg(buf+l, &rest)) != nil){ //fprint(2, "<<< %s\n", p); m = parsemsg(p); free(p); if(m == nil){ fprint(2, "garbled message: %s\n", p); goto cleanmsg; } handlemsg(c, m); freemsg(m); //fprint(2, "rest: '%s'\n", rest); if(rest[0] != 0){ strcpy(buf, rest); l = 0; goto more; } cleanmsg: memset(buf, 0, sizeof(buf)); l = 0; } l += n; } if(n < 0) fprint(2, "read: %r\n"); if(c->greeted > 0){ qlock(clnthash); delhash(clnthash, c->nick); qunlock(clnthash); } dbg("disconnected: %r"); freeclient(c); threadexits("EOF"); } void clientproc(void *) { Client *c; threadsetname("arbiter"); while(c = recvp(clntchan)){ threadsetname("arbiter"); threadcreate(clientthread, c, 16384); } } void listenproc(void *v) { int dfd, acfd, lcfd; char *addr, adir[40], ldir[40]; Client *c; addr = v; threadsetname("soothsayer %s", addr); acfd = announce(addr, adir); if(acfd < 0) sysfatal("announce: %r"); for(;;){ werrstr(""); lcfd = listen(adir, ldir); if(lcfd < 0){ fprint(2, "listen: %r\n"); sleep(1000); continue; } dfd = accept(lcfd, ldir); if(dfd < 0){ fprint(2, "accept: %r\n"); sleep(1000); continue; } c = mkclient(dfd, lcfd); sendp(clntchan, c); } } void threadmain(int argc, char **argv) { int daemon = 0; ARGBEGIN{ case 'd': daemon++; break; }ARGEND inithash(); clnthash = newhash(); chanhash = newhash(); clntchan = chancreate(sizeof(Client*), 0); myname = strdup(sysname()); char *addr = "tcp!*!6667"; proccreate(clientproc, nil, 4096); listenproc(addr); threadexitsall(nil); }