ref: abeb6b0542e9b7db6ce1ab102f03fc7499f54eb2
parent: e09ff804102de75826409b6043619d2668d9cef8
author: libredev <libredev@ircforever.org>
date: Wed Nov 23 11:36:01 EST 2022
replaced poll with picoev (event loop library)
--- /dev/null
+++ b/.gitmodules
@@ -1,0 +1,3 @@
+[submodule "picoev"]
+ path = picoev
+ url = https://github.com/kazuho/picoev
--- a/Makefile
+++ b/Makefile
@@ -6,9 +6,10 @@
CC = cc
CFLAGS = -g -std=c89 -Wall -Wextra -pedantic -Wfatal-errors -Wconversion\
-Wstrict-prototypes -Wold-style-definition\
- -D_POSIX_C_SOURCE=200809L
+ -D_POSIX_C_SOURCE=200809L -isystem ./picoev/
#CFLAGS += -fsanitize=address -fno-omit-frame-pointer
#LDFLAGS = -fsanitize=address
+LDFLAGS = -L ./picoev/ -l picoev
VERSION != date '+%Y-%m-%d'
PROGRAM = ticl
@@ -16,8 +17,11 @@
HEADERS = htable.h util.c
OBJECTS = $(SOURCES:.c=.o)
-all: clean $(PROGRAM)
+all: clean libpicoev.a $(PROGRAM)
+libpicoev.a:
+ cd picoev && $(MAKE) libpicoev.a CC=gcc LINUX_BUILD=1 CC_DEBUG_FLAGS=-g
+
$(PROGRAM): $(OBJECTS)
$(CC) -o $@ $(OBJECTS) $(LDFLAGS)
@@ -26,6 +30,7 @@
clean:
rm -f $(PROGRAM) $(OBJECTS) $(PROGRAM)-$(VERSION).tar.gz
+ cd picoev && $(MAKE) clean
dist: clean
mkdir -p $(PROGRAM)-$(VERSION)
--- a/main.c
+++ b/main.c
@@ -3,7 +3,6 @@
* See COPYING file for more information.
*/
-#include <fcntl.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
@@ -12,20 +11,23 @@
#include <time.h>
#include <unistd.h>
+#include <picoev.h>
+
#include "htable.h"
#include "util.c"
#define BUFFER_LEN 1024
-#define MAX_NICK_LEN 16
+#define NICK_LEN 16
-#define POLLFD_ADDEND 100
+#define EVENT_ADDEND 10000
#define NET_ADDEND 10
#define USER_ADDEND 100
+#define EVENT_TIMEOUT 10000
-#define TIME_OUT 180
+#define UNUSED(x) (void)(x)
-typedef struct {
- int id; /* fd of linker */
+struct network {
+ int id; /* event index */
int join; /* is joined */
char *name; /* name */
char *symb; /* symbol */
@@ -32,46 +34,51 @@
char *host; /* hostname */
char *port; /* port */
char *chan; /* channel */
-} Network;
+};
-/* user defined data for each fd */
-struct FdData {
+struct event {
+ int fd; /* event fd */
int netid; /* net index */
- int suffix; /* suffix count */
char *user; /* user nick */
- time_t time;
+ int suffix; /* suffix count */
};
-static struct pollfd *fdset; /* pollfd set */
-static struct FdData *fddata; /* user data set */
-static int fdslen; /* fdset length */
-static int fdscap; /* fdset capacity */
+static struct event *events; /* events array */
+static int evlen; /* array length */
+static int evcap; /* array capacity */
-static Network *networks; /* linked list of networks */
-static int netlen; /* current network length */
-static int netcap; /* total memory allocated */
-static Htable *users; /* users-clones hash table */
+static struct network *networks; /* networks array */
+static int netlen; /* array length */
+static int netcap; /* array capacity */
-char msg[BUFFER_LEN];
-static int isrunning = 1;
+/*
+ * hash table of users
+ * key -> <user_nick> + '[' + <network_symbol> + ']'
+ * value -> array of all user's clones event ids indexed
+ * corresponding to its connected network
+ */
+static struct Htable *users;
+static char msg [BUFFER_LEN];
+static int done;
+
/* functions prototype */
-void handle_fifo_input(int, char *);
-void handle_server_output(int);
-void net_add(char *, char *, char *, char *, char *);
-void net_del(char *);
+void fifo_event_cb(picoev_loop *, int, int, void *);
+void server_event_cb(picoev_loop *, int, int, void *);
+void net_add(picoev_loop *, char *, char *, char *, char *, char *);
+void net_del(picoev_loop *, char *);
void net_del_raw(int);
-void net_update(int);
-void user_add(char *, int);
-void user_del(char *, char *);
-int *user_ids(char *, int);
-int *euserids(char *);
-int clone_add(char *, int);
-int fdset_add(int, int, int, char *);
-void fdset_del(int);
+void net_update(picoev_loop *, int);
+void user_add(picoev_loop *, char *, int);
+void user_del(picoev_loop *, char *, char *);
+int *user_get_ids(char *);
+int *clone_get_user_ids(char *, int);
+int clone_add(picoev_loop *, char *, int);
+int event_add(picoev_loop *, int, int, char *);
+void event_del(picoev_loop *, int);
void nick_add_symb(char *, int);
void privmsg_update(char *, char *, int);
-void terminate(int);
+void clean_exit(picoev_loop *, int);
void print_table(void);
void print_htable(void);
void print_users(void);
@@ -80,8 +87,8 @@
int
main(int argc, char *argv[])
{
- int i, n, timeout_id;
- time_t last_time, timeout;
+ picoev_loop *loop;
+ int fd;
/* set stdout to unbufferd */
setvbuf(stdout, NULL, _IONBF, 0);
@@ -93,88 +100,52 @@
}
/* init global variables */
- fdscap = POLLFD_ADDEND;
- fdset = ecalloc((size_t)fdscap, sizeof(struct pollfd));
- fddata = ecalloc((size_t)fdscap, sizeof(struct FdData));
+ evcap = EVENT_ADDEND;
netcap = NET_ADDEND;
- networks = ecalloc((size_t)netcap, sizeof(Network));
- /*
- * hash table of users
- * key -> <nickname> + '[' + <network_symbol> + ']'
- * value -> array of linked clones fds indexed
- * corresponding to its connected network
- */
+ events = ecalloc((size_t)evcap, sizeof(struct event));
+ networks = ecalloc((size_t)netcap, sizeof(struct network));
users = htcreate((KeyLenFn *)strlen, (KeyCmpFn *)strcmp, free, free, USER_ADDEND);
- /* add fifo_fd */
- fdset_add(fifo_open(argv[1]), -1, -1, NULL);
+ /* init picoev */
+ picoev_init(1000);
+ /* create loop */
+ loop = picoev_create_loop(60);
+ /* get fifo fd */
+ fd = fifo_open(argv[1]);
+ /* add fifo fd */
+ picoev_add(loop, fd, PICOEV_READ, 0, fifo_event_cb, argv[1]);
+ /* loop */
+ while (!done)
+ picoev_loop_once(loop, 10);
+ /* clean and exit */
+ clean_exit(loop, 0);
- /* select loop */
- while (isrunning) {
- /* calculate timeout from fdset */
- last_time = time(NULL);
- for (i = 0; i < fdslen; i++) {
- if ((fddata[i].netid != -1) /* ignore fifo */
- && (fddata[i].time < last_time)) {
- last_time = fddata[i].time;
- timeout_id = i;
- }
- }
- timeout = TIME_OUT - (time(NULL) - last_time);
- if (timeout < 0)
- timeout = 0;
-
- n = poll(fdset, (nfds_t)fdslen, (int)timeout * 1000);
- if (n == -1) {
- printf("error: poll: %s\n", strerror(errno));
- terminate(1);
- } else if (n == 0) {
- snprintf(msg, sizeof(msg), "PING :%s\r\n",
- networks[fddata[timeout_id].netid].host);
- writeall(fdset[timeout_id].fd, msg);
- fddata[timeout_id].time = time(NULL);
- continue;
- }
- for (i = 0; i < fdslen; i++) {
- if (!(fdset[i].revents & (POLLIN|POLLHUP)))
- continue;
- if (fddata[i].netid == -1)
- handle_fifo_input(i, argv[1]);
- else
- handle_server_output(i);
-
- fddata[i].time = time(NULL);
-
- /*
- * handle one ready fd at one time because if we
- * close upcoming ready fd, it cause infinite loop.
- */
- break;
- }
- }
- terminate(0);
return 0;
}
void
-handle_fifo_input(int id, char *path)
+fifo_event_cb(picoev_loop *loop, int fd, int revents, void *cb_arg)
{
- char buffer[BUFFER_LEN];
- char *buf;
- char *cmd;
- ssize_t n;
+ char buffer[BUFFER_LEN];
+ char *buf;
+ char *cmd;
+ ssize_t n;
- /* if failed to read data */
- if ((n = readline(fdset[id].fd, buffer, sizeof(buffer))) < 1) {
- if (n == 0) { /* restart again */
- fdset_del(id);
- fdset_add(fifo_open(path), -1, -1, NULL);
- } else if ((errno != EAGAIN) && (errno != EINTR)) {
- printf("error: %d: read: %s\n", fdset[id].fd, strerror(errno));
- }
+ UNUSED(revents);
+
+ n = readline(fd, buffer, sizeof(buffer));
+ if (n == -1) {
+ if (errno == EAGAIN || errno == EWOULDBLOCK)
+ return;
+ printf("error: %d: read: %s\n", fd, strerror(errno));
+ clean_exit(loop, 1);
+ } else if (n == 0) { /* reopen fifo again */
+ picoev_del(loop, fd);
+ close(fd);
+ fd = fifo_open((char *)cb_arg);
+ picoev_add(loop, fd, PICOEV_READ, 0, fifo_event_cb, cb_arg);
return;
}
- /* printf("fifo: %s\n", buffer); */
buf = buffer;
cmd = split(&buf, ' ');
@@ -187,13 +158,13 @@
if (!*name || !*symb || !*host || !*port || !*chan)
printf("usage: netadd <name> <symbol> <hostname> <port> <channel>\n");
else
- net_add(name, symb, host, port, chan);
+ net_add(loop, name, symb, host, port, chan);
} else if (strcmp(cmd, "netdel") == 0) {
char *name = buf;
if (!*name)
printf("usage: netdel <name>\n");
else
- net_del(name);
+ net_del(loop, name);
} else if (strcmp(cmd, "print") == 0) {
print_table();
} else if (strcmp(cmd, "htable") == 0) {
@@ -201,7 +172,7 @@
} else if (strcmp(cmd, "users") == 0) {
print_users();
} else if (strcmp(cmd, "exit") == 0) {
- isrunning = 0;
+ done = 1;
} else {
printf("error: %s is not a command\n", cmd);
}
@@ -208,32 +179,46 @@
}
void
-handle_server_output(int id)
+server_event_cb(picoev_loop *loop, int fd, int revents, void *cb_arg)
{
- char buffer [BUFFER_LEN];
- char backup [BUFFER_LEN];
- char linker_nick [MAX_NICK_LEN];
- char *buf;
- char *cmd;
- char *nick;
- int i, netid;
- ssize_t n;
+ char buffer [BUFFER_LEN];
+ char backup [BUFFER_LEN];
+ char lnick [NICK_LEN]; /* linker nick */
+ char *buf;
+ char *cmd;
+ char *nick;
+ int i, id, netid;
+ ssize_t n;
- /* if failed to read data */
- if ((n = readline(fdset[id].fd, buffer, sizeof(buffer))) < 1) {
- if (n == 0) {
- printf("error: %d: connection closed\n", fdset[id].fd);
- printf("ping: %d : %ld\n", fdset[id].fd, time(0) - fddata[id].time);
- terminate(1);
- /* fdset_del(fdset[id].fd); */
- } else if ((errno != EAGAIN) && (errno != EINTR)) {
- printf("error: %d: read: %s\n", fdset[id].fd, strerror(errno));
- printf("ping: %d : %ld\n", fdset[id].fd, time(0) - fddata[id].time);
- terminate(1);
+ id = (int)((struct event *)cb_arg - events);
+ netid = events[id].netid;
+
+ if ((revents & PICOEV_WRITE) != 0) {
+ if (events[id].user == NULL) { /* linker */
+ snprintf(msg, sizeof(msg), "NICK linker\r\n");
+ writeall(fd, msg);
+ snprintf(msg, sizeof(msg), "USER linker 0 * :linker\r\n");
+ writeall(fd, msg);
+ } else { /* user */
+ snprintf(msg, sizeof(msg), "NICK %s\r\n", events[id].user);
+ writeall(fd, msg);
+ snprintf(msg, sizeof(msg), "USER user 0 * :user\r\n");
+ writeall(fd, msg);
}
- return;
+ picoev_set_events(loop, fd, PICOEV_READ);
}
+ n = readline(fd, buffer, sizeof(buffer));
+ if (n == -1) {
+ if (errno == EAGAIN || errno == EWOULDBLOCK)
+ return;
+ printf("error: read: %d: %s\n", fd, strerror(errno));
+ clean_exit(loop, 1);
+ } else if (n == 0) { /* reopen fifo again */
+ printf("error: closed: %d\n", fd);
+ clean_exit(loop, 1);
+ }
+
/* remove CRLFs */
for (i = 0; i < (int)strlen(buffer); i++) {
if (buffer[i] == '\r' || buffer[i] == '\n') {
@@ -246,11 +231,10 @@
strcpy(backup, buffer);
buf = buffer;
- netid = fddata[id].netid;
/* set linker nick */
- strcpy(linker_nick, "linker");
- for (i = 0; i < fddata[id].suffix; i++)
- strcat(linker_nick, "_");
+ strcpy(lnick, "linker");
+ for (i = 0; i < events[id].suffix; i++)
+ strcat(lnick, "_");
/* first column */
cmd = split(&buf, ' ');
@@ -260,7 +244,7 @@
goto printbuffer;
} else if (strcmp(cmd, "PING") == 0) {
snprintf(msg, sizeof(msg), "PONG %s\r\n", buf);
- writeall(fdset[id].fd, msg);
+ writeall(fd, msg);
return;
}
/* strip nick from first column */
@@ -296,30 +280,30 @@
} else if (strcmp(cmd, "433") == 0) { /* Nickname already in use */
split(&buf, ' ');
nick = split(&buf, ' ');
- if (strlen(nick)+1 > MAX_NICK_LEN) {
+ if (strlen(nick)+1 > NICK_LEN) {
printf("error: cannot append suffix, nick '%s' is too big\n", nick);
- if (strcmp(nick, linker_nick) == 0) {
- net_del(networks[netid].name);
+ if (strcmp(nick, lnick) == 0) {
+ net_del(loop, networks[netid].name);
} else {
snprintf(msg, sizeof(msg), "QUIT :nick is too big\r\n");
- user_del(nick, msg);
+ user_del(loop, nick, msg);
}
} else {
strcat(nick, "_");
- fddata[id].suffix++;
+ events[id].suffix++;
snprintf(msg, sizeof(msg), "NICK %s\r\n", nick);
- writeall(fdset[id].fd, msg);
+ writeall(fd, msg);
}
return;
} else if (strcmp(cmd, "001") == 0) {
snprintf(msg, sizeof(msg), "JOIN %s\r\n", networks[netid].chan);
- writeall(fdset[id].fd, msg);
+ writeall(fd, msg);
return;
} else if (strcmp(cmd, "PRIVMSG") == 0) {
char privmsg[BUFFER_LEN] = "";
int *ids;
- if (fddata[id].user == NULL) { /* if linker */
+ if (events[id].user == NULL) { /* if linker */
nick_add_symb(nick, netid);
if ((ids = htsearch(users, nick)) == NULL)
return;
@@ -329,7 +313,7 @@
for (i = 0; i < netlen; i++) {
if (ids[i] > 0) {
snprintf(msg, sizeof(msg), "PRIVMSG %s :%s\r\n", networks[i].chan, privmsg);
- writeall(fdset[ids[i]].fd, msg);
+ writeall(events[ids[i]].fd, msg);
}
}
} else {
@@ -358,12 +342,12 @@
split(&buf, ':'); /* set buf to msg */
privmsg_update(privmsg, buf, netid);
snprintf(msg, sizeof(msg), "PRIVMSG %s :%s\r\n", user, privmsg);
- writeall(fdset[ids[i]].fd, msg);
+ writeall(events[ids[i]].fd, msg);
}
return;
}
/* these messages are handled by linker */
- if (fddata[id].user != NULL) { /* if clone */
+ if (events[id].user != NULL) { /* if clone */
if ((strcmp(cmd, "353") == 0)
|| (strcmp(cmd, "JOIN") == 0)
|| (strcmp(cmd, "QUIT") == 0)
@@ -375,7 +359,7 @@
char *nick;
split(&buf, ':');
networks[netid].join = 1;
- net_update(netid);
+ net_update(loop, netid);
while (*(nick = split(&buf, ' ')) != '\0') {
if (*nick == '@'
|| *nick == '&'
@@ -384,14 +368,14 @@
|| *nick == '+'
|| *nick == '\\')
nick++;
- if (strcmp(nick, linker_nick) != 0)
- user_add(nick, netid);
+ if (strcmp(nick, lnick) != 0)
+ user_add(loop, nick, netid);
}
return;
} else if (strcmp(cmd, "JOIN") == 0) {
- if ((strcmp(nick, linker_nick) != 0)
- && (user_ids(nick, netid) == NULL)) /* if not clone */
- user_add(nick, netid);
+ if ((strcmp(nick, lnick) != 0)
+ && (clone_get_user_ids(nick, netid) == NULL)) /* if not clone */
+ user_add(loop, nick, netid);
return;
} else if ((strcmp(cmd, "QUIT") == 0)
|| (strcmp(cmd, "PART") == 0)) {
@@ -398,7 +382,7 @@
snprintf(msg, sizeof(msg), "QUIT :%s\r\n", buf);
nick_add_symb(nick, netid);
if (htsearch(users, nick) != NULL)
- user_del(nick, msg);
+ user_del(loop, nick, msg);
return;
} else if (strcmp(cmd, "NICK") == 0) {
int *ids, i;
@@ -418,7 +402,7 @@
snprintf(msg, sizeof(msg), "NICK %s\r\n", newnick);
for (i = 0; i < netlen; i++) {
if (ids[i] > 0)
- writeall(fdset[ids[i]].fd, msg);
+ writeall(events[ids[i]].fd, msg);
}
return;
} else if (strcmp(cmd, "KICK") == 0) {
@@ -431,21 +415,21 @@
snprintf(msg, sizeof(msg), "QUIT : kicked by %s\r\n", nick);
/* delete whole network if it is the linker */
- if (strcmp(user, linker_nick) == 0) {
- net_del(networks[netid].name);
+ if (strcmp(user, lnick) == 0) {
+ net_del(loop, networks[netid].name);
return;
}
/* delete the user if the message from the same network */
- if ((ids = user_ids(user, netid)) == NULL) {
+ if ((ids = clone_get_user_ids(user, netid)) == NULL) {
nick_add_symb(user, netid);
- user_del(user, msg);
+ user_del(loop, user, msg);
return;
}
/* close the kicked fd */
- writeall(fdset[ids[netid]].fd, msg);
- fdset_del(id);
+ writeall(fd, msg);
+ event_del(loop, id);
/*
* send notice in the channel through linker
@@ -463,18 +447,18 @@
snprintf(msg, sizeof(msg),
"PRIVMSG %s :%s was kicked out by %s from network %s %s [%s]\r\n",
networks[i].chan, user, nick, networks[netid].name, chan, buf);
- writeall(fdset[networks[i].id].fd, msg);
+ writeall(events[networks[i].id].fd, msg);
return;
}
printbuffer:
- printf("%d: %s\n", fdset[id].fd, backup);
+ printf("%d: %s\n", fd, backup);
}
void
-net_add(char *name, char *symb, char *host, char *port, char *chan)
+net_add(picoev_loop *loop, char *name, char *symb, char *host, char *port, char *chan)
{
- int i, fd;
- Network *n;
+ int i, fd;
+ struct network *n;
/* if name, symbol or configuration already exists */
for (i = 0; i < netlen; i++) {
@@ -497,7 +481,7 @@
/* resize if full */
if (netlen == netcap) {
Htiter it = {0};
- networks = erecalloc(networks, (size_t)netcap, NET_ADDEND, sizeof(Network));
+ networks = erecalloc(networks, (size_t)netcap, NET_ADDEND, sizeof(struct network));
while (htiterate(users, &it))
it.node->val = erecalloc(it.node->val, (size_t)netcap, NET_ADDEND, sizeof(int));
netcap += NET_ADDEND;
@@ -506,14 +490,9 @@
/* connect */
if ((fd = dial(host, port)) == -1)
return;
- /* send NICK and USER commands */
- snprintf(msg, sizeof(msg), "NICK linker\r\n");
- writeall(fd, msg);
- snprintf(msg, sizeof(msg), "USER linker 0 * :linker\r\n");
- writeall(fd, msg);
/* add a network */
n = &networks[netlen];
- n->id = fdset_add(fd, netlen, 0, NULL);
+ n->id = event_add(loop, fd, netlen, NULL);
n->join = 0;
n->name = strdup(name);
n->symb = strdup(symb);
@@ -525,7 +504,7 @@
}
void
-net_del(char *name)
+net_del(picoev_loop *loop, char *name)
{
int i, netid, *ids;
@@ -553,14 +532,14 @@
ids = (int *)it.node->val;
/* delete all the users of deleting network */
if (ids[netid] == -1) {
- user_del(it.node->key, msg);
+ user_del(loop, it.node->key, msg);
/* this node is deleted */
it = lastit;
/* delete the clones */
} else {
if (ids[netid] > 0) {
- writeall(fdset[ids[netid]].fd, msg);
- fdset_del(ids[netid]);
+ writeall(events[ids[netid]].fd, msg);
+ event_del(loop, ids[netid]);
}
/* swap last with current one */
ids[netid] = ids[netlen-1];
@@ -568,16 +547,16 @@
lastit = it;
}
- /* set netid of fds with last netid to current netid. */
- for (i = 0; i < fdslen; i++) {
- if (fddata[i].netid == netlen-1)
- fddata[i].netid = netid;
+ /* set last netid of events to current netid. */
+ for (i = 0; i < evlen; i++) {
+ if (events[i].netid == netlen-1)
+ events[i].netid = netid;
}
- writeall(fdset[networks[netid].id].fd, msg);
- fdset_del(networks[netid].id);
+ writeall(events[networks[netid].id].fd, msg);
+ event_del(loop, networks[netid].id);
net_del_raw(netid);
- printf("%d: network '%s' deleted\n", fdset[networks[netid].id].fd, name);
+ printf("%d: network '%s' deleted\n", events[networks[netid].id].fd, name);
/* swap the network with the last */
networks[netid] = networks[netlen-1];
netlen--;
@@ -586,7 +565,7 @@
void
net_del_raw(int netid)
{
- Network *n = &networks[netid];
+ struct network *n = &networks[netid];
free(n->name);
free(n->symb);
free(n->host);
@@ -595,15 +574,15 @@
}
void
-net_update(int netid)
+net_update(picoev_loop *loop, int netid)
{
Htiter it = {0};
while (htiterate(users, &it))
- ((int *)it.node->val)[netid] = clone_add(it.node->key, netid);
+ ((int *)it.node->val)[netid] = clone_add(loop, it.node->key, netid);
}
void
-user_add(char *unick, int netid)
+user_add(picoev_loop *loop, char *unick, int netid)
{
int i, *ids;
size_t len;
@@ -612,12 +591,12 @@
len = strlen(unick) + strlen(networks[netid].symb) + 2 + 1;
/* too long nick */
- if (len-1 > MAX_NICK_LEN) {
+ if (len - 1 > NICK_LEN) {
printf("error: user nick '%s' is too big\n", unick);
return;
}
- /* resize hash table if store is low */
+ /* resize hash table if storage is low */
if ((users->cap - users->len) < USER_ADDEND)
htresize(users, users->cap + USER_ADDEND);
@@ -635,7 +614,7 @@
if (i == netid) {
ids[i] = -1;
} else {
- ids[i] = clone_add(nick, i);
+ ids[i] = clone_add(loop, nick, i);
}
}
/* insert it to the users hash table */
@@ -642,19 +621,20 @@
if (htinsert(users, nick, ids) == -1) {
/* this shouldn't happen as it was already checked */
printf("error: user '%s' already exists\n", nick);
- terminate(1);
+ clean_exit(loop, 1);
}
}
void
-user_del(char *nick, char *msg)
+user_del(picoev_loop *loop, char *nick, char *msg)
{
int i;
- int *ids = euserids(nick);
+ int *ids = user_get_ids(nick);
+
for (i = 0; i < netlen; i++) {
if (ids[i] > 0) {
- writeall(fdset[ids[i]].fd, msg);
- fdset_del(ids[i]);
+ writeall(events[ids[i]].fd, msg);
+ event_del(loop, ids[i]);
}
}
htremove(users, nick);
@@ -661,8 +641,19 @@
}
int *
-user_ids(char *nick, int netid)
+user_get_ids(char *user)
{
+ int *ids;
+ if ((ids = htsearch(users, user)) == NULL) {
+ printf("error: cannot find user '%s'\n", user);
+ exit(1);
+ }
+ return ids;
+}
+
+int *
+clone_get_user_ids(char *nick, int netid)
+{
unsigned int suffix;
int *ids = NULL;
@@ -674,7 +665,7 @@
ids = htsearch(users, nick);
/* if match but suffix doesn't match */
- if ((ids != NULL) && (fddata[ids[netid]].suffix != (int)suffix))
+ if ((ids != NULL) && (events[ids[netid]].suffix != (int)suffix))
ids = NULL;
/* add suffix back */
@@ -684,68 +675,64 @@
return ids;
}
-/* get user ids */
-int *
-euserids(char *user)
-{
- int *ids;
- if ((ids = htsearch(users, user)) == NULL) {
- printf("error: cannot find user '%s'\n", user);
- terminate(1);
- }
- return ids;
-}
-
int
-clone_add(char *nick, int netid)
+clone_add(picoev_loop *loop, char *nick, int netid)
{
- int fd;
- Network *n = &networks[netid];
+ int fd;
+ struct network *n = &networks[netid];
+
if ((fd = dial(n->host, n->port)) == -1)
return -1;
- /* send NICK and USER commands */
- snprintf(msg, sizeof(msg), "NICK %s\r\n", nick);
- writeall(fd, msg);
- snprintf(msg, sizeof(msg), "USER user 0 * :user\r\n");
- writeall(fd, msg);
- return fdset_add(fd, netid, 0, nick);
+ return event_add(loop, fd, netid, nick);
}
int
-fdset_add(int fd, int netid, int suffix, char *user)
+event_add(picoev_loop *loop, int fd, int netid, char *user)
{
- if (fdslen == fdscap) {
- fdset = erecalloc(fdset, (size_t)fdscap, POLLFD_ADDEND, sizeof(struct pollfd));
- fddata = erecalloc(fddata, (size_t)fdscap, POLLFD_ADDEND, sizeof(struct FdData));
- fdscap += POLLFD_ADDEND;
+ int i = evlen;
+
+ if (evlen == evcap) {
+ events = erecalloc(events, (size_t)evcap, EVENT_ADDEND, sizeof(struct event));
+ evcap += EVENT_ADDEND;
}
- fdset[fdslen].fd = fd;
- fdset[fdslen].events = POLLIN;
- fddata[fdslen].netid = netid;
- fddata[fdslen].suffix = suffix;
- fddata[fdslen].user = user;
- fddata[fdslen].time = time(NULL);
- return fdslen++;
+
+ events[i].fd = fd;
+ events[i].netid = netid;
+ events[i].user = user;
+ events[i].suffix = 0;
+ picoev_add(loop, fd, PICOEV_WRITE, 0, server_event_cb, &events[i]);
+
+ return evlen++;
}
void
-fdset_del(int id)
+event_del(picoev_loop *loop, int id)
{
- /* set id of last fd to current id */
- if (fddata[fdslen-1].user != NULL)
- euserids(fddata[fdslen-1].user)[fddata[fdslen-1].netid] = id;
- else if ((fddata[fdslen-1].user == NULL) && (fddata[fdslen-1].netid != -1))
- networks[fddata[fdslen-1].netid].id = id;
- /* set id of removing fd to -2 */
- if (fddata[id].user != NULL)
- euserids(fddata[id].user)[fddata[id].netid] = -2;
- else if ((fddata[id].user == NULL) && (fddata[id].netid != -1))
- networks[fddata[id].netid].id = -2;
+ int *ids;
+ int l = evlen - 1; /* last id */
- close(fdset[id].fd);
- fdset[id] = fdset[fdslen-1];
- fddata[id] = fddata[fdslen-1];
- fdslen--;
+ /* swap id */
+ if (events[l].user == NULL) { /* if linker */
+ networks[events[l].netid].id = id;
+ } else { /* if user */
+ ids = user_get_ids(events[l].user);
+ ids[events[l].netid] = id;
+ }
+
+ /* disable id */
+ if (events[id].user == NULL) { /* if linker */
+ networks[events[id].netid].id = -2;
+ } else { /* if user */
+ ids = user_get_ids(events[id].user);
+ ids[events[id].netid] = -2;
+ }
+
+ picoev_del(loop, events[id].fd);
+ close(events[id].fd);
+
+ events[id] = events[l];
+ events[id] = events[l];
+ evlen--;
}
void
@@ -777,7 +764,7 @@
}
/* check if the word is nick */
- if (user_ids(src, netid) != NULL)
+ if (clone_get_user_ids(src, netid) != NULL)
*strrchr(src, '[') = '\0';
strcat(dst, src);
@@ -788,15 +775,17 @@
}
void
-terminate(int status)
+clean_exit(picoev_loop *loop, int status)
{
int i;
snprintf(msg, sizeof(msg), "QUIT :linker shutting down\r\n");
- for (i = 0; i < fdslen; i++) {
- if (fddata[i].netid != -1)
- writeall(fdset[i].fd, msg);
- fdset_del(i);
+ for (i = 0; i < evlen; i++) {
+ writeall(events[i].fd, msg);
+ event_del(loop, i);
}
+ picoev_destroy_loop(loop);
+ picoev_deinit();
+
/* delete all the users */
htdestroy(users);
@@ -805,8 +794,7 @@
net_del_raw(i);
free(networks);
- free(fdset);
- free(fddata);
+ free(events);
if (status == 0) {
printf("exit successfully\n");
@@ -829,9 +817,9 @@
print_border();
/* print networks */
- printf("Networks\t\t");
+ printf("struct networks\t\t");
for (i = 0; i < netlen; i++)
- printf("%s(%d)\t", networks[i].symb, fdset[networks[i].id].fd);
+ printf("%s(%d)\t", networks[i].symb, events[networks[i].id].fd);
printf("\n");
while (htiterate(users, &it)) {
@@ -846,8 +834,8 @@
for (i = 0; i < netlen; i++) {
printf("%d", ids[i]);
/* print suffix */
- if ((ids[i] > 0) && (fddata[ids[i]].suffix > 0))
- printf("(%d)", fddata[ids[i]].suffix);
+ if ((ids[i] > 0) && (events[ids[i]].suffix > 0))
+ printf("(%d)", events[ids[i]].suffix);
printf("\t");
}
printf("\n");