ticl

tiny irc channel linker
git clone git://git.ircforever.org/ticl
Log | Files | Refs | Submodules | README | LICENSE

commit fb90d152ef67420872ed6f7a479b0fa6f201a725
parent 202447793107a549c7e418dc3b2208caa89a0bb3
Author: libredev <libredev@ircforever.org>
Date:   Wed, 15 Feb 2023 22:45:58 +0530

implemented re-connection

Diffstat:
Mmain.c | 461++++++++++++++++++++++++++++++++++++++++++++++++++++---------------------------
Mutil.c | 15---------------
2 files changed, 302 insertions(+), 174 deletions(-)

diff --git a/main.c b/main.c @@ -29,6 +29,7 @@ char *strlcpy(char *dst, const char *src, size_t n) #define CLONE_COOLDOWN 1 #define CLONE_ADDEND 10 +#define RECONN_TIME 10 #define FD_ADDEND 100 #define NET_ADDEND 10 @@ -45,16 +46,22 @@ enum { IDLE = 0, RESET, CLONING, - DONE + EXIT }; -struct vuser { +struct fd_data { char *user; /* nick */ int netid; /* net index */ int suffix; /* suffix count */ 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 int kqfd; /* kqueue instance */ 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 @@ time_t event_timeout(void); 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 @@ main(int argc, char *argv[]) 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 @@ main(int argc, char *argv[]) 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 @@ main(int argc, char *argv[]) fd_register(fifofd, EV_READ); /* event loop */ - while (state != DONE) { + while (state != EXIT) { if (ntime == -1) { timeout = -1; } else { @@ -192,38 +205,31 @@ main(int argc, char *argv[]) } 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 @@ fifo_read(void) 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 @@ fifo_read(void) 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 @@ event_timeout(void) 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 @@ event_timeout(void) 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,15 +399,11 @@ fd_write(int fd) fatal("kevent:"); fd_register(fd, EV_READ); #endif - if (fdtovuser[fd]->user == NULL) { /* linker */ - snprintf(msg, sizeof(msg), "NICK linker\r\n"); - writeall(fd, msg); - snprintf(msg, sizeof(msg), "USER linker 0 * :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); } else { /* user */ - snprintf(msg, sizeof(msg), "NICK %s\r\n", fdtovuser[fd]->user); - writeall(fd, msg); - snprintf(msg, sizeof(msg), "USER user 0 * :user\r\n"); + snprintf(msg, sizeof(msg), "NICK %s\r\nUSER user 0 * :user\r\n", fdtodata[fd]->user); writeall(fd, msg); } } @@ -385,24 +413,26 @@ fd_read(int fd) { char buffer [BUFSIZE]; char backup [BUFSIZE]; - char lnick [NICK_LEN]; /* linker nick */ + char wnick [NICK_LEN]; /* watcher nick */ char *buf; char *cmd; char *nick; 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,17 +441,20 @@ fd_read(int fd) 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, ' '); 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 @@ fd_read(int fd) 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 @@ fd_read(int fd) 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 @@ fd_read(int fd) 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 @@ fd_read(int fd) 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 @@ fd_read(int fd) *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 @@ fd_read(int fd) 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 @@ fd_read(int fd) 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,49 +640,41 @@ fd_read(int fd) 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++) { 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,51 +726,74 @@ net_add(char *name, char *symb, char *host, char *port, char *chan) 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); 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--; -} - -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 (n->fd > 0) + fd_del(n->fd, msg, reconnect); + else if (n->fd == -3) + reconn_list_del(NULL, netid); + + 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 @@ user_add(char *unick, int netid, int clone) 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 @@ user_add(char *unick, int netid, int clone) } 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, 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; } - htremove(usertofds, nick); + 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 @@ vuser_add(int netid, char *user) 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 @@ vuser_get_fds(char *nick, int netid) 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 @@ privmsg_update(char *dst, char *src, int netid) } /* 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 @@ print_table(void) 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 @@ print_table(void) 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 @@ print_users(void) } 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; @@ -1012,3 +1136,22 @@ print_border(void) 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; +} diff --git a/util.c b/util.c @@ -208,21 +208,6 @@ readline(int fd, char *buffer, size_t size) 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)