]> jfr.im git - irc/quakenet/newserv.git/blame - nickrate/nickrate.c
CHANSERV: fix issue where chanserv_relay doesn't wait for db to be loaded before...
[irc/quakenet/newserv.git] / nickrate / nickrate.c
CommitLineData
c86edd1d
Q
1#include "../server/server.h"
2#include "../core/hooks.h"
3#include "../core/events.h"
4#include "../nick/nick.h"
5#include <sys/poll.h>
6#include <sys/types.h>
7#include <sys/socket.h>
8#include <netdb.h>
9#include "../core/error.h"
10#include <stdlib.h>
11#include <stdio.h>
12#include <errno.h>
13#include <sys/ioctl.h>
14#include <unistd.h>
15#include <netinet/in.h>
4ad1cf7a 16#include <string.h>
7f32dbdf
P
17#include "../lib/version.h"
18
19MODULE_VERSION("")
c86edd1d
Q
20
21unsigned int nicks;
22unsigned int quits;
aaa47a15 23int nickrate_listenfd;
c86edd1d
Q
24
25void nr_nick(int hooknum, void *arg);
26void nr_handlelistensocket(int fd, short events);
27int nr_openlistensocket(int portnum);
28
29void _init() {
30 nicks=0;
31 quits=0;
32 registerhook(HOOK_NICK_NEWNICK, &nr_nick);
33 registerhook(HOOK_NICK_LOSTNICK, &nr_nick);
34
aaa47a15 35 nickrate_listenfd=nr_openlistensocket(6002);
36 if (nickrate_listenfd>0) {
37 registerhandler(nickrate_listenfd,POLLIN,&nr_handlelistensocket);
c86edd1d
Q
38 }
39
40}
41
42void _fini() {
43 deregisterhook(HOOK_NICK_NEWNICK, &nr_nick);
44 deregisterhook(HOOK_NICK_LOSTNICK, &nr_nick);
aaa47a15 45 deregisterhandler(nickrate_listenfd,1);
c86edd1d
Q
46}
47
48void nr_nick(int hooknum, void *arg) {
49 nick *np=(nick *)arg;
50
51 if (serverlist[homeserver(np->numeric)].linkstate == LS_LINKED) {
52 if (hooknum==HOOK_NICK_NEWNICK) {
53 nicks++;
54 } else {
55 quits++;
56 }
57 }
58}
59
60int nr_openlistensocket(int portnum) {
61 struct sockaddr_in sin;
62 int fd;
63 unsigned int opt=1;
64
65 if ((fd=socket(AF_INET,SOCK_STREAM,0))==-1) {
66 Error("proxyscan",ERR_ERROR,"Unable to open listening socket (%d).",errno);
67 return -1;
68 }
69
70 if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (const char *) &opt, sizeof(opt))!=0) {
71 Error("proxyscan",ERR_ERROR,"Unable to set SO_REUSEADDR on listen socket.");
72 return -1;
73 }
74
75 /* Initialiase the addresses */
76 memset(&sin,0,sizeof(sin));
77 sin.sin_family=AF_INET;
78 sin.sin_port=htons(portnum);
79
80 if (bind(fd, (struct sockaddr *) &sin, sizeof(sin))) {
81 Error("proxyscan",ERR_ERROR,"Unable to bind listen socket (%d).",errno);
82 return -1;
83 }
84
85 listen(fd,5);
86
87 if (ioctl(fd, FIONBIO, &opt)!=0) {
88 Error("proxyscan",ERR_ERROR,"Unable to set listen socket non-blocking.");
89 return -1;
90 }
91
92 return fd;
93}
94
95/* Here's what we do when poll throws the listen socket at us:
96 * accept() the connection, spam a short message and immediately
97 * close it again */
98
99void nr_handlelistensocket(int fd, short events) {
100 struct sockaddr_in sin;
101 socklen_t addrsize=sizeof(sin);
102 char buf[20];
103 int newfd;
104 if ((newfd=accept(fd, (struct sockaddr *)&sin, &addrsize))>0) {
105 /* Got new connection */
106 sprintf(buf,"%u\n",nicks);
107 write(newfd,buf,strlen(buf));
108 sprintf(buf,"%u\n",quits);
109 write(newfd,buf,strlen(buf));
110 close(newfd);
111 }
112}