]>
Commit | Line | Data |
---|---|---|
1 | #include <stdio.h> | |
2 | #include <time.h> | |
3 | #include "../lib/version.h" | |
4 | #include "../dbapi2/dbapi2.h" | |
5 | #include "../core/error.h" | |
6 | #include "../core/hooks.h" | |
7 | #include "../core/schedule.h" | |
8 | #include "../server/server.h" | |
9 | #include "../control/control.h" | |
10 | ||
11 | MODULE_VERSION("") | |
12 | ||
13 | static DBAPIConn *db; | |
14 | ||
15 | static void hook_server(int hook, void *arg); | |
16 | static void create_entry(unsigned long servernum, int start_transaction); | |
17 | static int list_numerics(void *source, int cargc, char **cargv); | |
18 | static void rescan_network(void); | |
19 | static void rescan_network_s(void *arg); | |
20 | ||
21 | void _init(void) { | |
22 | db = dbapi2open(NULL, "numerictracker"); | |
23 | if(!db) { | |
24 | Error("numerictracker", ERR_WARNING, "Unable to connect to db -- not loaded."); | |
25 | return; | |
26 | } | |
27 | ||
28 | db->createtable(db, NULL, NULL, "CREATE TABLE ? (numeric VARCHAR(2) NOT NULL, server_name VARCHAR(?), last_seen INT, PRIMARY KEY (numeric, server_name));", "Td", "numerics", HOSTLEN); | |
29 | ||
30 | registerhook(HOOK_SERVER_NEWSERVER, &hook_server); | |
31 | registerhook(HOOK_SERVER_LOSTSERVER, &hook_server); | |
32 | rescan_network(); | |
33 | schedulerecurring(time(NULL)+60*5, 0, 60*5, rescan_network_s, NULL); | |
34 | ||
35 | registercontrolhelpcmd("listnumerics", NO_OPER, 0, list_numerics, "Usage: listnumerics\nLists all numeric-servername pairs ever seen by the service."); | |
36 | } | |
37 | ||
38 | void _fini(void) { | |
39 | if(!db) | |
40 | return; | |
41 | ||
42 | deregisterhook(HOOK_SERVER_NEWSERVER, &hook_server); | |
43 | deregisterhook(HOOK_SERVER_LOSTSERVER, &hook_server); | |
44 | deregistercontrolcmd("listnumerics", list_numerics); | |
45 | deleteallschedules(rescan_network_s); | |
46 | } | |
47 | ||
48 | static void rescan_network() { | |
49 | int i; | |
50 | ||
51 | db->squery(db, "BEGIN TRANSACTION;", ""); | |
52 | ||
53 | for(i=0;i<MAXSERVERS;i++) | |
54 | if(serverlist[i].linkstate != LS_INVALID) | |
55 | create_entry(i, 0); | |
56 | ||
57 | db->squery(db, "COMMIT;", ""); | |
58 | } | |
59 | ||
60 | static void rescan_network_s(void *arg) { | |
61 | rescan_network(); | |
62 | } | |
63 | ||
64 | static void hook_server(int hook, void *arg) { | |
65 | unsigned long servernum = (unsigned long)arg; | |
66 | ||
67 | create_entry(servernum, 1); | |
68 | } | |
69 | ||
70 | static void create_entry(unsigned long servernum, int start_transaction) { | |
71 | char *server_name = serverlist[servernum].name->content; | |
72 | char *numeric = longtonumeric(servernum, 2); | |
73 | ||
74 | if(start_transaction) | |
75 | db->squery(db, "BEGIN TRANSACTION;", ""); | |
76 | ||
77 | db->squery(db, "DELETE FROM ? WHERE numeric = ? AND server_name = ?;", "Tss", "numerics", numeric, server_name); | |
78 | db->squery(db, "INSERT INTO ? (numeric, server_name, last_seen) VALUES (?, ?, ?);", "Tsst", "numerics", numeric, server_name, time(NULL)); | |
79 | ||
80 | if(start_transaction) | |
81 | db->squery(db, "COMMIT;", ""); | |
82 | } | |
83 | ||
84 | static void list_numerics_callback(const DBAPIResult *result, void *tag) { | |
85 | nick *sender = getnickbynumeric((unsigned long)tag); | |
86 | ||
87 | if(!result) { | |
88 | if(sender) | |
89 | controlreply(sender, "DB query error 1."); | |
90 | return; | |
91 | } | |
92 | ||
93 | if(!sender || !result->success || (result->fields != 3)) { | |
94 | if(sender) | |
95 | controlreply(sender, "DB query error 2."); | |
96 | ||
97 | result->clear(result); | |
98 | return; | |
99 | } | |
100 | ||
101 | controlreply(sender, "%s %-50s %s", "NN", "Server name", "Last seen"); | |
102 | while(result->next(result)) { | |
103 | char *numeric; | |
104 | char *server_name; | |
105 | time_t last_seen; | |
106 | char timebuf[50]; | |
107 | ||
108 | numeric = result->get(result, 0); | |
109 | server_name = result->get(result, 1); | |
110 | last_seen = strtoul(result->get(result, 2), NULL, 10); | |
111 | ||
112 | strftime(timebuf, sizeof(timebuf), "%d/%m/%y %H:%M GMT", gmtime(&last_seen)); | |
113 | controlreply(sender, " %s %-50s %s", numeric, server_name, timebuf); | |
114 | } | |
115 | result->clear(result); | |
116 | ||
117 | controlreply(sender, "End of listing."); | |
118 | } | |
119 | ||
120 | static int list_numerics(void *source, int cargc, char **cargv) { | |
121 | nick *sender = (nick *)source; | |
122 | ||
123 | rescan_network(); | |
124 | db->query(db, list_numerics_callback, (void *)sender->numeric, "SELECT numeric, server_name, last_seen FROM ? ORDER BY last_seen ASC, numeric, server_name", "T", "numerics"); | |
125 | ||
126 | return CMD_OK; | |
127 | } |