commit 5fc053455f7402fa975b1b50dc3903258bbab188
parent 66b3d1bfa7dcc42bc6bd047eacf83863d8bc8cd4
Author: hhvn <dev@hhvn.uk>
Date: Sun, 19 Dec 2021 22:07:40 +0000
s/main.c s/serv.c s/handle.c s/struct.h s/hirc.h: buffered reading
Diffstat:
5 files changed, 66 insertions(+), 50 deletions(-)
diff --git a/src/handle.c b/src/handle.c
@@ -588,31 +588,13 @@ handle_logonly(char *msg, char **params, struct Server *server, time_t timestamp
}
void
-handle(struct Server *server) {
+handle(struct Server *server, char *msg) {
time_t timestamp;
char **params;
char *cmd;
char *schmsg;
- char *msg;
- char buf[511];
- /* using a buffer size of 511:
- * - RFC1459 defines the maximum size of a message to be 512
- * - read_line() doesn't copy the \r\n so this is reduced to 510
- * - a \0 is needed at the end, so 510 + 1 = 511 */
int i;
- memset(buf, '\0', sizeof(buf));
- if (!ircgets(server, buf, sizeof(buf))) {
- if (buf[0] == EOF || buf[0] == 3 || buf[0] == 4) {
- serv_disconnect(server, 1, "EOF");
- hist_format(server->history, Activity_error, HIST_SHOW,
- "SELF_CONNECTLOST %s %s %s :EOF received",
- server->name, server->host, server->port);
- }
- return;
- }
- msg = buf;
-
if (*msg == '!' && strchr(msg, ' ') && *(strchr(msg, ' ')+1) && *(msg+1) != ' ') {
msg++;
timestamp = (time_t)strtoll(msg, NULL, 10);
diff --git a/src/hirc.h b/src/hirc.h
@@ -111,7 +111,7 @@ char * schedule_pull(struct Server *server, char *tmsg);
int serv_ischannel(struct Server *server, char *str);
/* handle.c */
-void handle(struct Server *server);
+void handle(struct Server *server, char *msg);
void handle_expect(struct Server *server, enum Expect cmd, char *about);
char * handle_expect_get(struct Server *server, enum Expect cmd);
diff --git a/src/main.c b/src/main.c
@@ -124,35 +124,6 @@ param_create(char *msg) {
}
int
-ircgets(struct Server *server, char *buf, size_t buf_len) {
- size_t i = 0;
- char c = 0;
-
- do {
-#ifdef TLS
- if (server->tls) {
- switch (tls_read(server->tls_ctx, &c, sizeof(char))) {
- case -1:
- return 0;
- case TLS_WANT_POLLIN:
- case TLS_WANT_POLLOUT:
- continue;
- }
- } else {
-#endif /* TLS */
- if (read(server->rfd, &c, sizeof(char)) != sizeof(char))
- return 0;
-#ifdef TLS
- }
-#endif /* TLS */
- if (c != '\r')
- buf[i++] = c;
- } while (c != '\n' && i < buf_len);
- buf[i - 1] = '\0';
- return 1;
-}
-
-int
read_line(int fd, char *buf, size_t buf_len) {
size_t i = 0;
char c = 0;
@@ -167,6 +138,65 @@ read_line(int fd, char *buf, size_t buf_len) {
return 1;
}
+void
+ircread(struct Server *sp) {
+ char *line, *end;
+ int ret;
+
+ if (!sp)
+ return;
+
+#ifdef TLS
+ if (sp->tls) {
+ switch (ret = tls_read(sp->tls_ctx, &sp->inputbuf[sp->inputlen], SERVER_INPUT_SIZE - sp->inputlen - 1)) {
+ case 0:
+ serv_disconnect(sp, 1, "EOF");
+ hist_format(sp->history, Activity_error, HIST_SHOW,
+ "SELF_CONNECTLOST %s %s %s :connection closed",
+ sp->name, sp->host, sp->port);
+ return;
+ case -1:
+ ui_tls_error(sp->tls_ctx, "tls_read()");
+ return;
+ case TLS_WANT_POLLIN:
+ case TLS_WANT_POLLOUT:
+ return;
+ default:
+ sp->inputlen += ret;
+ break;
+ }
+ } else {
+#endif /* TLS */
+ switch (ret = read(sp->rfd, &sp->inputbuf[sp->inputlen], SERVER_INPUT_SIZE - sp->inputlen - 1)) {
+ case 0:
+ serv_disconnect(sp, 1, "EOF");
+ hist_format(sp->history, Activity_error, HIST_SHOW,
+ "SELF_CONNECTLOST %s %s %s :connection closed",
+ sp->name, sp->host, sp->port);
+ return;
+ case -1:
+ ui_perror("read()");
+ return;
+ default:
+ sp->inputlen += ret;
+ break;
+ }
+#ifdef TLS
+ }
+#endif /* TLS */
+
+ sp->inputbuf[SERVER_INPUT_SIZE - 1] = '\0';
+ line = sp->inputbuf;
+ while (end = strstr(line, "\r\n")) {
+ *end = '\0';
+ handle(sp, line);
+ line = end + 2;
+ }
+
+ sp->inputlen -= line - sp->inputbuf;
+ memmove(sp->inputbuf, line, sp->inputlen);
+}
+
int
ircprintf(struct Server *server, char *format, ...) {
char msg[512];
@@ -330,7 +360,7 @@ main(int argc, char *argv[]) {
sp->pingsent = 0;
sp->lastrecv = time(NULL);
sp->rpollfd->revents = 0;
- handle(sp);
+ ircread(sp);
} else if (!sp->pingsent && sp->lastrecv && (time(NULL) - sp->lastrecv) >= pinginact) {
/* haven't heard from server in pinginact seconds, sending a ping */
ircprintf(sp, "PING :ground control to Major Tom\r\n");
diff --git a/src/serv.c b/src/serv.c
@@ -76,6 +76,7 @@ serv_create(char *name, char *host, char *port, char *nick,
server = emalloc(sizeof(struct Server));
server->prev = server->next = NULL;
server->wfd = server->rfd = server->logfd = -1;
+ server->inputlen = 0;
server->rpollfd = emalloc(sizeof(struct pollfd));
server->rpollfd->fd = -1;
server->rpollfd->events = POLLIN;
diff --git a/src/struct.h b/src/struct.h
@@ -125,10 +125,13 @@ struct Schedule {
struct Schedule *next;
};
+#define SERVER_INPUT_SIZE 1024
struct Server {
struct Server *prev;
int wfd;
int rfd;
+ char inputbuf[SERVER_INPUT_SIZE];
+ int inputlen;
struct pollfd *rpollfd;
int logfd;
enum ConnStatus status;