ref: fb90d152ef67420872ed6f7a479b0fa6f201a725
parent: 202447793107a549c7e418dc3b2208caa89a0bb3
author: libredev <libredev@ircforever.org>
date: Wed Feb 15 17:45:58 EST 2023
implemented re-connection
--- a/main.c
+++ b/main.c
@@ -29,6 +29,7 @@
#define CLONE_COOLDOWN 1
#define CLONE_ADDEND 10
+#define RECONN_TIME 10
#define FD_ADDEND 100
#define NET_ADDEND 10
@@ -45,10 +46,10 @@
IDLE = 0,
RESET,
CLONING,
- DONE
+ EXIT
};
-struct vuser {
+struct fd_data {
char *user; /* nick */
int netid; /* net index */
int suffix; /* suffix count */
@@ -55,6 +56,12 @@
int ready; /* joined */
};
+struct fd_ref {
+ char *user; /* nick */
+ int netid; /* net index */
+ struct fd_ref *next; /* next node */
+};
+
struct network {
int fd; /* fd */
char *name; /* name */
@@ -80,11 +87,14 @@
static struct network *networks; /* networks array */
static int netlen; /* array length */
static int netcap; /* array capacity */
-static struct vuser **fdtovuser; /* fd -> vuser pointer */
-static int fdcap; /* fdtovuser capacity */
+static struct fd_data **fdtodata; /* fd -> data pointer */
+static int fdcap; /* fdtodata capacity */
static struct htable *usertofds; /* user -> array of fds of clones
indexed according to networks array */
+static struct fd_ref *reconn_list_head, /* re-connection queue */
+ *reconn_list_tail;
+
/* functions prototype */
void fd_register(int, int);
void fifo_read(void);
@@ -92,19 +102,23 @@
void fd_write(int);
void fd_read(int);
void net_add(char *, char *, char *, char *, char *);
-void net_del(int, char *);
-void net_del_raw(int);
+void net_del(int, char *, int);
void user_add(char *, int, int);
void user_del(char *, char *);
-int vuser_add(int, char *);
-void vuser_del(int, char *);
-int *vuser_get_fds(char *, int);
+void reconn_list_add(char *, int);
+void reconn_list_del(char *, int);
+int fd_new(int, char *);
+void fd_del(int, char *, int);
+void fd_reconn(int, char *);
+int *clone_get_fds(char *, int);
void nick_add_symb(char *, int);
void privmsg_update(char *, char *, int);
void print_table(void);
void print_htable(void);
void print_users(void);
+void print_reconn_list(void);
void print_border(void);
+ssize_t writeall(int, char *);
int
main(int argc, char *argv[])
@@ -115,9 +129,8 @@
struct kevent kevs[HANDLE_EVENTS];
struct timespec tmsp;
#endif
- int i, fd, *fds, nev; /* no. of returned events to handle */
+ int i, fd, nev; /* no. of returned events to handle */
time_t timeout;
- struct htiter it;
/* set stdout to unbufferd */
setvbuf(stdout, NULL, _IONBF, 0);
@@ -132,7 +145,7 @@
netcap = NET_ADDEND;
fdcap = FD_ADDEND;
networks = emalloc((size_t)netcap * sizeof(struct network));
- fdtovuser = emalloc((size_t)fdcap * sizeof(struct vuser *));
+ fdtodata = emalloc((size_t)fdcap * sizeof(struct fd_data *));
usertofds = htcreate(hash_str, (key_cmp_fn *)strcmp, free, free,
USER_ADDEND);
@@ -147,7 +160,7 @@
fd_register(fifofd, EV_READ);
/* event loop */
- while (state != DONE) {
+ while (state != EXIT) {
if (ntime == -1) {
timeout = -1;
} else {
@@ -192,38 +205,31 @@
} else if (kevs[i].filter == EVFILT_READ) {
#endif
fd_read(fd);
- if (break_evloop) {
- break_evloop = FALSE;
- break;
- }
} else {
fatal("unknown event");
}
+
+ if (reconn_list_head != NULL && ntime == -1)
+ ntime = time(0) + RECONN_TIME;
+ if (break_evloop) {
+ break_evloop = FALSE;
+ break;
+ }
}
}
- /* cleanup */
+ /*
+ * delete and free all the networks with their users
+ * - delete in reverse order to prevent swapping.
+ */
snprintf(msg, sizeof(msg), "QUIT :relay shutting down\r\n");
-
- /* delete and free all the users with their fds */
- htiter_init(&it);
- while(htiterate(usertofds, &it)) {
- fds = (int *)it.node->val;
- for (i = 0; i < netlen; i++) {
- if (fds[i] > 0)
- vuser_del(fds[i], msg);
- }
- }
- htdestroy(usertofds);
+ for (i = netlen-1; i >= 0; i--)
+ net_del(i, msg, FALSE);
- /* delete and free all the networks with their fd */
- for (i = 0; i < netlen; i++) {
- vuser_del(networks[i].fd, msg);
- net_del_raw(i);
- }
free(networks);
-
- free(fdtovuser);
+ free(fdtodata);
+ printf("table len: %d\n", usertofds->len);
+ htdestroy(usertofds);
return 0;
}
@@ -302,7 +308,7 @@
for (i = 0; i < netlen; i++) {
if (strcmp(name, networks[i].name) == 0) {
snprintf(msg, sizeof(msg), "QUIT :unlinking %s\r\n", networks[i].name);
- net_del(i, msg);
+ net_del(i, msg, FALSE);
return;
}
}
@@ -314,8 +320,10 @@
print_htable();
} else if (strcmp(cmd, "users") == 0) {
print_users();
+ } else if (strcmp(cmd, "reconn") == 0) {
+ print_reconn_list();
} else if (strcmp(cmd, "exit") == 0) {
- state = DONE;
+ state = EXIT;
} else {
warnf("%s is not a command", cmd);
}
@@ -329,7 +337,30 @@
int i, j, *fds;
char *user;
- if (state == RESET) {
+ if (state == IDLE) {
+ struct fd_ref *tmp;
+ log1("Reconnecting");
+ while(reconn_list_head != NULL) {
+ user = reconn_list_head->user;
+ i = reconn_list_head->netid;
+
+ if (user == NULL) {
+ networks[i].fd = fd_new(i, user);
+ } else {
+ if ((fds = htsearch(usertofds, user)) == NULL)
+ fatal("%s: user doesn't exist", user);
+ if (fds[i] == -3 &&
+ networks[i].fd > 0 &&
+ fdtodata[networks[i].fd]->ready)
+ fds[i] = fd_new(i, user);
+ }
+ tmp = reconn_list_head;
+ reconn_list_head = reconn_list_head->next;
+ free(tmp);
+ }
+ reconn_list_tail = reconn_list_head;
+ return -1;
+ } else if (state == RESET) {
state = CLONING;
htiter_init(&it);
}
@@ -340,8 +371,9 @@
user = (char *)it.node->key;
fds = (int *)it.node->val;
for (i = 0; i < netlen; i++) {
- if (fds[i] == 0 && fdtovuser[networks[i].fd]->ready)
- fds[i] = vuser_add(i, user);
+ if (fds[i] == 0 && networks[i].fd > 0 &&
+ fdtodata[networks[i].fd]->ready)
+ fds[i] = fd_new(i, user);
}
j++;
if (j >= CLONE_ADDEND)
@@ -367,16 +399,12 @@
fatal("kevent:");
fd_register(fd, EV_READ);
#endif
- if (fdtovuser[fd]->user == NULL) { /* linker */
- snprintf(msg, sizeof(msg), "NICK linker\r\n");
+ if (fdtodata[fd]->user == NULL) { /* watcher */
+ snprintf(msg, sizeof(msg), "NICK watcher\r\nUSER watcher 0 * :watcher\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", fdtovuser[fd]->user);
+ snprintf(msg, sizeof(msg), "NICK %s\r\nUSER user 0 * :user\r\n", fdtodata[fd]->user);
writeall(fd, msg);
- snprintf(msg, sizeof(msg), "USER user 0 * :user\r\n");
- writeall(fd, msg);
}
}
@@ -385,7 +413,7 @@
{
char buffer [BUFSIZE];
char backup [BUFSIZE];
- char lnick [NICK_LEN]; /* linker nick */
+ char wnick [NICK_LEN]; /* watcher nick */
char *buf;
char *cmd;
char *nick;
@@ -392,17 +420,19 @@
int i, netid;
ssize_t n;
- netid = fdtovuser[fd]->netid;
+ netid = fdtodata[fd]->netid;
n = readline(fd, buffer, sizeof(buffer));
if (n == -1) {
warnf("%d: read:", fd);
snprintf(msg, sizeof(msg), "QUIT :read failed\r\n");
- goto del;
+ fd_reconn(fd, msg);
+ return;
} else if (n == 0) {
- warnf("%d: connection closed", fd);
+ warnf("%d: read: connection closed", fd);
snprintf(msg, sizeof(msg), "QUIT :connection closed\r\n");
- goto del;
+ fd_reconn(fd, msg);
+ return;
}
if (*buffer == '\0')
return;
@@ -411,10 +441,10 @@
strlcpy(backup, buffer, sizeof(backup));
buf = buffer;
- /* set linker nick */
- strlcpy(lnick, "linker", sizeof(lnick));
- for (i = 0; i < fdtovuser[fd]->suffix; i++)
- strcat(lnick, "_");
+ /* set watcher nick */
+ strlcpy(wnick, "watcher", sizeof(wnick));
+ for (i = 0; i < fdtodata[fd]->suffix; i++)
+ strcat(wnick, "_");
/* first column */
cmd = split(&buf, ' ');
@@ -421,7 +451,10 @@
if (strcmp(cmd, "NOTICE") == 0) { /* ignore */
return;
} else if (strcmp(cmd, "ERROR") == 0) {
- fatal("%d: %s", fd, backup);
+ warnf("%d: %s", fd, backup);
+ snprintf(msg, sizeof(msg), "QUIT :ERROR\r\n");
+ fd_reconn(fd, msg);
+ return;
} else if (strcmp(cmd, "PING") == 0) {
snprintf(msg, sizeof(msg), "PONG %s\r\n", buf);
writeall(fd, msg);
@@ -466,11 +499,15 @@
split(&buf, ' ');
nick = split(&buf, ' ');
strcat(nick, "_");
- fdtovuser[fd]->suffix++;
+ fdtodata[fd]->suffix++;
if (strlen(nick) > NICK_LEN) {
warnf("%s: nickname too long", nick);
snprintf(msg, sizeof(msg), "QUIT :%s: nickname too long\r\n", nick);
- goto del;
+ if (fdtodata[fd]->user == NULL)
+ net_del(netid, msg, FALSE);
+ else
+ fd_del(fd, msg, FALSE);
+ return;
} else {
snprintf(msg, sizeof(msg), "NICK %s\r\n", nick);
writeall(fd, msg);
@@ -484,7 +521,7 @@
char privmsg[BUFSIZE] = "";
int *fds;
- if (fdtovuser[fd]->user == NULL) { /* if linker */
+ if (fdtodata[fd]->user == NULL) { /* if watcher */
nick_add_symb(nick, netid);
if ((fds = htsearch(usertofds, nick)) == NULL)
return;
@@ -501,7 +538,7 @@
char *netsymb;
char *user = split(&buf, ' ');
- /* ignore messages from channel (it is handled by linker) */
+ /* ignore messages from channel (it is handled by watcher) */
if (user[0] == '#' || user[0] == '&')
return;
@@ -528,20 +565,15 @@
return;
}
else if (strcmp(cmd, "353") == 0) {
- fdtovuser[fd]->ready = TRUE;
+ fdtodata[fd]->ready = TRUE;
/* FALLBACK */
}
- /* these messages are handled by linker */
- if (fdtovuser[fd]->user != NULL) { /* if clone */
- if ((strcmp(cmd, "353") == 0) ||
- (strcmp(cmd, "JOIN") == 0) ||
- (strcmp(cmd, "QUIT") == 0) ||
- (strcmp(cmd, "PART") == 0) ||
- (strcmp(cmd, "KICK") == 0) ||
- (strcmp(cmd, "NICK") == 0)) {
- return;
- }
- } else if (strcmp(cmd, "353") == 0) {
+
+ /* from now, the messages are handled by watcher */
+ if (fdtodata[fd]->user != NULL) /* if clone */
+ return;
+
+ if (strcmp(cmd, "353") == 0) {
char *nick;
split(&buf, ':');
state = RESET;
@@ -556,14 +588,14 @@
*nick == '+' ||
*nick == '\\')
nick++;
- if (strcmp(nick, lnick) != 0)
+ if (strcmp(nick, wnick) != 0)
user_add(nick, netid, FALSE);
}
return;
} else if (strcmp(cmd, "JOIN") == 0) {
/* if real user */
- if ((strcmp(nick, lnick) != 0) &&
- (vuser_get_fds(nick, netid) == NULL)) {
+ if ((strcmp(nick, wnick) != 0) &&
+ (clone_get_fds(nick, netid) == NULL)) {
if (state != IDLE)
warnf("%s: ignored (network cloning)", nick);
else
@@ -574,11 +606,8 @@
split(&buf, ':'); /* ignore ':' and assign QUIT/PART msg to buf */
snprintf(msg, sizeof(msg), "QUIT :%s\r\n", buf);
nick_add_symb(nick, netid);
- if (htsearch(usertofds, nick) != NULL) {
+ if (htsearch(usertofds, nick) != NULL)
user_del(nick, msg);
- break_evloop = TRUE;
- return;
- }
return;
} else if (strcmp(cmd, "NICK") == 0) {
int *fds, i;
@@ -597,7 +626,7 @@
snprintf(msg, sizeof(msg), "NICK %s\r\n", newnick);
for (i = 0; i < netlen; i++) {
if (fds[i] > 0) {
- fdtovuser[fds[i]]->user = newnick;
+ fdtodata[fds[i]]->user = newnick;
writeall(fds[i], msg);
}
}
@@ -611,27 +640,25 @@
user = split(&buf, ' '); /* user who is being kicked */
split(&buf, ':'); /* ignore ':' and store reason to buf */
- /* if linker is being kicked, delete the network */
- if (strcmp(user, lnick) == 0) {
+ /* if watcher is being kicked, delete the network */
+ if (strcmp(user, wnick) == 0) {
snprintf(msg, sizeof(msg), "QUIT :netdel: %s (%s is kicked by %s)\r\n",
- networks[netid].name, lnick, nick);
- net_del(netid, msg);
- break_evloop = TRUE;
+ networks[netid].name, wnick, nick);
+ fd_reconn(fd, msg);
return;
}
/* if message is from a real user, delete the user */
- if ((fds = vuser_get_fds(user, netid)) == NULL) {
+ if ((fds = clone_get_fds(user, netid)) == NULL) {
snprintf(msg, sizeof(msg), "QUIT :userdel: %s (kicked by %s)\r\n", user, nick);
nick_add_symb(user, netid);
user_del(user, msg);
- break_evloop = TRUE;
return;
}
/* delete the kicked clone */
snprintf(msg, sizeof(msg), "QUIT :kicked by %s\r\n", nick);
- vuser_del(fds[netid], msg);
+ fd_reconn(fds[netid], msg);
/* get the original user netid */
for (i = 0; i < netlen; i++) {
@@ -638,22 +665,16 @@
if (fds[i] == -1)
break;
}
- /* send notice in the channel through linker */
- snprintf(msg, sizeof(msg), "PRIVMSG %s :%s is kicked by %s [%s]\r\n",
- networks[i].chan, user, nick, buf);
- writeall(networks[i].fd, msg);
- break_evloop = TRUE;
+ /* send notice in the channel through watcher */
+ if (networks[i].fd > 0) {
+ snprintf(msg, sizeof(msg), "PRIVMSG %s :%s is kicked by %s [%s]\r\n",
+ networks[i].chan, user, nick, buf);
+ writeall(networks[i].fd, msg);
+ }
return;
}
warnf("%d: %s", fd, backup);
return;
-del:
- if (fdtovuser[fd]->user == NULL)
- net_del(netid, msg);
- else
- vuser_del(fd, msg);
- break_evloop = TRUE;
- return;
}
void
@@ -705,19 +726,23 @@
n->host = strdup(host);
n->port = strdup(port);
n->chan = strdup(chan);
- n->fd = vuser_add(netlen, NULL);
+ n->fd = fd_new(netlen, NULL);
netlen++;
}
void
-net_del(int netid, char *msg)
+net_del(int netid, char *msg, int reconnect)
{
int *fds;
+ char *user;
+ struct network *n;
struct htiter lit, it; /* last, current iterator */
+ n = &networks[netid];
htiter_init(&it);
htiter_init(&lit);
while (htiterate(usertofds, &it)) {
+ user = (char *)it.node->key;
fds = (int *)it.node->val;
if (fds[netid] == -1) {
user_del(it.node->key, msg);
@@ -724,32 +749,51 @@
it = lit; /* this node is deleted */
} else {
if (fds[netid] > 0)
- vuser_del(fds[netid], msg);
- fds[netid] = fds[netlen-1];
- if (fds[netid] > 0)
- fdtovuser[fds[netid]]->netid = netid;
- fds[netlen-1] = 0;
+ fd_del(fds[netid], msg, FALSE);
+ else if (fds[netid] == -3)
+ reconn_list_del(user, netid);
+
+ if (!reconnect) {
+ if(netid != netlen-1) {
+ fds[netid] = fds[netlen-1];
+ if (fds[netid] > 0) {
+ fdtodata[fds[netid]]->netid = netid;
+ } else if (fds[netid] == -3) {
+ reconn_list_del(user, netlen-1);
+ reconn_list_add(user, netid);
+ }
+ }
+ fds[netlen-1] = 0;
+ } else {
+ fds[netid] = 0;
+ }
}
lit = it;
}
- vuser_del(networks[netid].fd, msg);
- net_del_raw(netid);
- networks[netid] = networks[netlen-1];
- if (networks[netid].fd > 0)
- fdtovuser[networks[netid].fd]->netid = netid;
- netlen--;
-}
+ if (n->fd > 0)
+ fd_del(n->fd, msg, reconnect);
+ else if (n->fd == -3)
+ reconn_list_del(NULL, netid);
-void
-net_del_raw(int netid)
-{
- struct network *n = &networks[netid];
- free(n->name);
- free(n->symb);
- free(n->host);
- free(n->port);
- free(n->chan);
+ if (!reconnect) {
+ free(n->name);
+ free(n->symb);
+ free(n->host);
+ free(n->port);
+ free(n->chan);
+ /* swap */
+ if(netid != netlen-1) {
+ networks[netid] = networks[netlen-1];
+ if (networks[netid].fd > 0) {
+ fdtodata[n->fd]->netid = netid;
+ } else if (networks[netid].fd == -3) {
+ reconn_list_del(NULL, netlen-1);
+ reconn_list_add(NULL, netid);
+ }
+ }
+ netlen--;
+ }
}
void
@@ -778,8 +822,9 @@
if (clone) {
int i;
for (i = 0; i < netlen; i++) {
- if (fds[i] == 0 && fdtovuser[networks[i].fd]->ready)
- fds[i] = vuser_add(i, nick);
+ if (fds[i] == 0 && networks[i].fd > 0 &&
+ fdtodata[networks[i].fd]->ready)
+ fds[i] = fd_new(i, nick);
}
}
@@ -788,25 +833,74 @@
}
void
-user_del(char *nick, char *msg)
+user_del(char *user, char *msg)
{
int i, *fds;
- if ((fds = htsearch(usertofds, nick)) == NULL)
- fatal("%s: user doesn't exist", nick);
+ if ((fds = htsearch(usertofds, user)) == NULL)
+ fatal("%s: user doesn't exist", user);
for (i = 0; i < netlen; i++) {
- if (fds[i] > 0)
- vuser_del(fds[i], msg);
+ if (fds[i] > 0) {
+ fd_del(fds[i], msg, FALSE);
+ } else if (fds[i] == -3) {
+ reconn_list_del(user, i);
+ }
}
- htremove(usertofds, nick);
+ htremove(usertofds, user);
}
+void
+reconn_list_add(char *user, int netid)
+{
+ struct fd_ref *node;
+
+ node = emalloc(sizeof(struct fd_ref));
+ node->user = user;
+ node->netid = netid;
+ node->next = NULL;
+ if (reconn_list_tail == NULL) {
+ reconn_list_head = reconn_list_tail = node;
+ } else {
+ reconn_list_tail->next = node;
+ reconn_list_tail = reconn_list_tail->next;
+ }
+}
+
+void
+reconn_list_del(char *user, int netid)
+{
+ struct fd_ref *n, *pn; /* current and previous node */
+
+ n = reconn_list_head;
+ pn = NULL;
+ while (n != NULL) {
+ if (n->netid == netid &&
+ ((user == NULL && n->user == NULL) ||
+ (user != NULL && n->user != NULL &&
+ (strcmp(n->user, user) == 0)))) {
+ if (n == reconn_list_head && n == reconn_list_tail)
+ reconn_list_head = reconn_list_tail = NULL;
+ else if (n == reconn_list_head)
+ reconn_list_head = n->next;
+ else if (n == reconn_list_tail)
+ reconn_list_tail = pn;
+ else
+ pn->next = n->next;
+ free(n);
+ return;
+ }
+ pn = n;
+ n = n->next;
+ }
+ fatal("%d:%s: failed to find in re-connection list", netid, user);
+}
+
int
-vuser_add(int netid, char *user)
+fd_new(int netid, char *user)
{
int fd;
struct network *n;
- struct vuser *vuser;
+ struct fd_data *data;
n = &networks[netid];
fd = dial(n->host, n->port);
@@ -823,46 +917,62 @@
if (fd+1 > fdcap) {
fdcap *= 2;
- fdtovuser = erealloc(fdtovuser, (size_t)fdcap * sizeof(struct vuser *));
+ fdtodata = erealloc(fdtodata, (size_t)fdcap * sizeof(struct fd_data *));
}
- vuser = emalloc(1 * sizeof(struct vuser));
- vuser->netid = netid;
- vuser->user = user;
- vuser->suffix = 0;
- vuser->ready = FALSE;
+ data = emalloc(1 * sizeof(struct fd_data));
+ data->netid = netid;
+ data->user = user;
+ data->suffix = 0;
+ data->ready = FALSE;
- fdtovuser[fd] = vuser;
+ fdtodata[fd] = data;
return fd;
}
void
-vuser_del(int fd, char *msg)
+fd_del(int fd, char *msg, int reconnection)
{
- char *user = fdtovuser[fd]->user;
- int netid = fdtovuser[fd]->netid;
- int *fds;
+ char *user;
+ int netid;
+ int *fds;
+ user = fdtodata[fd]->user;
+ netid = fdtodata[fd]->netid;
+
if (user == NULL) {
log1("%d: netdel: %s[%s]", fd, networks[netid].name, networks[netid].symb);
- networks[netid].fd = -2;
+ networks[netid].fd = reconnection ? -3 : -2;
} else {
log1("%d: del[%s]: %s", fd, networks[netid].symb, user);
if ((fds = htsearch(usertofds, user)) == NULL)
fatal("%s: user doesn't exist", user);
- fds[netid] = -2;
+ fds[netid] = reconnection ? -3 : -2;
}
- if (fdtovuser[fd]->ready)
+ if (fdtodata[fd]->ready)
writeall(fd, msg);
close(fd);
- free(fdtovuser[fd]);
- fdtovuser[fd] = NULL;
+
+ if (reconnection)
+ reconn_list_add(user, netid);
+ free(fdtodata[fd]);
+ fdtodata[fd] = NULL;
+ break_evloop = TRUE;
}
+void
+fd_reconn(int fd, char *msg)
+{
+ if (fdtodata[fd]->user == NULL)
+ net_del(fdtodata[fd]->netid, msg, TRUE);
+ else
+ fd_del(fd, msg, TRUE);
+}
+
int *
-vuser_get_fds(char *nick, int netid)
+clone_get_fds(char *nick, int netid)
{
unsigned int s;
int *fds = NULL;
@@ -875,7 +985,7 @@
fds = htsearch(usertofds, nick);
/* if match but suffix doesn't match */
- if ((fds != NULL) && (fdtovuser[fds[netid]]->suffix != (int)s))
+ if ((fds != NULL) && (fdtodata[fds[netid]]->suffix != (int)s))
fds = NULL;
/* add suffix back */
@@ -914,7 +1024,7 @@
}
/* check if the word is nick */
- if (vuser_get_fds(src, netid) != NULL)
+ if (clone_get_fds(src, netid) != NULL)
*strrchr(src, '[') = '\0';
strcat(dst, src);
@@ -940,8 +1050,8 @@
for (i = 0; i < netlen; i++) {
printf("%s->%d", networks[i].symb, networks[i].fd);
/* print suffix */
- if (fdtovuser[networks[i].fd]->suffix > 0)
- printf("(%d)\t", fdtovuser[networks[i].fd]->suffix);
+ if (networks[i].fd > 0 && fdtodata[networks[i].fd]->suffix > 0)
+ printf("(%d)\t", fdtodata[networks[i].fd]->suffix);
else
printf("\t\t");
}
@@ -960,8 +1070,8 @@
for (i = 0; i < netlen; i++) {
printf("%d", fds[i]);
/* print suffix */
- if ((fds[i] > 0) && (fdtovuser[fds[i]]->suffix > 0))
- printf("(%d)", fdtovuser[fds[i]]->suffix);
+ if ((fds[i] > 0) && (fdtodata[fds[i]]->suffix > 0))
+ printf("(%d)", fdtodata[fds[i]]->suffix);
printf("\t\t");
}
printf("\n");
@@ -1005,6 +1115,20 @@
}
void
+print_reconn_list(void)
+{
+ struct fd_ref *n;
+
+ print_border();
+ n = reconn_list_head;
+ while(n != NULL) {
+ printf("%d: %s\n", n->netid, n->user);
+ n = n->next;
+ }
+ print_border();
+}
+
+void
print_border(void)
{
int i;
@@ -1011,4 +1135,23 @@
for (i = 0; i < 64; i++)
printf("-");
printf("\n");
+}
+
+ssize_t
+writeall(int fd, char *buf)
+{
+ ssize_t left, sent, n;
+ left = (ssize_t)strlen(buf);
+ sent = 0;
+ while (sent < left) {
+ if ((n = write(fd, buf+sent, (size_t)left)) == -1) {
+ warnf("%d: write:", fd);
+ snprintf(msg, sizeof(msg), "QUIT :write failed\r\n");
+ fd_reconn(fd, msg);
+ return -1;
+ }
+ sent += n;
+ left -= n;
+ }
+ return sent;
}
--- a/util.c
+++ b/util.c
@@ -208,21 +208,6 @@
return (ssize_t)i;
}
-ssize_t
-writeall(int fd, char *buf)
-{
- ssize_t left, sent, n;
- left = (ssize_t)strlen(buf);
- sent = 0;
- while (sent < left) {
- if ((n = write(fd, buf+sent, (size_t)left)) == -1)
- fatal("%d: write:", fd);
- sent += n;
- left -= n;
- }
- return sent;
-}
-
/* very simple string hash function */
unsigned int
hash_str(void *key, unsigned int cap)