Terminate and send response outside of file/dir branch

This commit is contained in:
Camden Dixie O'Brien 2022-10-14 11:33:31 +01:00
parent 120a97189f
commit 58c7b6feab

81
main.c
View File

@ -56,16 +56,6 @@ void handle_exit_signal(int signum)
exit_requested = true; exit_requested = true;
} }
static int retrying_write(int fd, const char *buf, size_t len)
{
int n;
do {
errno = 0;
n = write(fd, buf, len);
} while (errno == EINTR);
return n;
}
static int append_selector_part(const char *part, size_t partlen, char *buf, static int append_selector_part(const char *part, size_t partlen, char *buf,
size_t bufsize) size_t bufsize)
{ {
@ -162,8 +152,10 @@ int main(int argc, char *argv[])
struct sockaddr_in6 paddr; struct sockaddr_in6 paddr;
socklen_t paddr_size = sizeof(paddr); socklen_t paddr_size = sizeof(paddr);
int cfd; int cfd;
ssize_t n, slen; ssize_t n, slen, rlen;
while (!exit_requested) { while (!exit_requested) {
n = slen = rlen = 0;
/* /*
* Accept incoming connection. * Accept incoming connection.
* *
@ -283,7 +275,6 @@ int main(int argc, char *argv[])
* endings is done with a buffered reading approach to * endings is done with a buffered reading approach to
* minimize syscalls (as opposed to using fgetc()). * minimize syscalls (as opposed to using fgetc()).
*/ */
unsigned rpos = 0;
while (true) { while (true) {
/* Fill fbuf from file. */ /* Fill fbuf from file. */
n = fread(fbuf, sizeof(*fbuf), FBUF_SIZE, rf); n = fread(fbuf, sizeof(*fbuf), FBUF_SIZE, rf);
@ -295,38 +286,24 @@ int main(int argc, char *argv[])
/* Copy from fbuf to rbuf, replacing LF with CRLF. */ /* Copy from fbuf to rbuf, replacing LF with CRLF. */
for (unsigned fpos = 0; fpos < n; ++fpos) { for (unsigned fpos = 0; fpos < n; ++fpos) {
if (fbuf[fpos] == '\n') { if (fbuf[fpos] == '\n') {
if (RBUF_SIZE - rpos < 2) { if (RBUF_SIZE - rlen < 2) {
fprintf(stderr, "Response buffer is too small"); fprintf(stderr, "Response buffer is too small");
goto close_client_socket; goto close_client_socket;
} }
rbuf[rpos++] = '\r'; rbuf[rlen++] = '\r';
rbuf[rpos++] = '\n'; rbuf[rlen++] = '\n';
} else { } else {
if (RBUF_SIZE - rpos < 1) { if (RBUF_SIZE - rlen < 1) {
fprintf(stderr, "Response buffer is too small"); fprintf(stderr, "Response buffer is too small");
goto close_client_socket; goto close_client_socket;
} }
rbuf[rpos++] = fbuf[fpos]; rbuf[rlen++] = fbuf[fpos];
} }
} }
if (feof(rf)) if (feof(rf))
break; break;
} }
/*
* Terminate and send the response.
*/
if (RBUF_SIZE - rpos < RESP_TERM_LEN) {
fprintf(stderr, "Response buffer is too small");
goto close_client_socket;
}
memcpy(&rbuf[rpos], RESP_TERM, RESP_TERM_LEN);
rpos += RESP_TERM_LEN;
if (retrying_write(cfd, rbuf, rpos) == -1) {
fprintf(stderr, "Failed to write response to client\n");
goto close_client_socket;
}
} else if (S_ISDIR(rstat.st_mode)) { } else if (S_ISDIR(rstat.st_mode)) {
/* /*
* Open the directory. * Open the directory.
@ -390,25 +367,17 @@ int main(int argc, char *argv[])
continue; continue;
/* /*
* Format and send response line for current entry. * Format response line for current entry.
*/ */
n = snprintf(rbuf, RBUF_SIZE, "%1u%s\t%s\t%s\t%u\r\n", type, n = snprintf(&rbuf[rlen], RBUF_SIZE - rlen,
ent->d_name, &pbuf[srvroot_len], HOST, PORT); "%1u%s\t%s\t%s\t%u\r\n", type, ent->d_name,
if (n >= RBUF_SIZE) { &pbuf[srvroot_len], HOST, PORT);
fprintf(stderr, if (n >= RBUF_SIZE - rlen) {
"Response buffer was too small, skipping entry\n"); fprintf(stderr, "Response buffer was too small\n");
continue;
}
if (retrying_write(cfd, rbuf, n) != n) {
fprintf(stderr, "Error sending respose line to client\n");
continue;
}
}
if (retrying_write(cfd, ".\r\n", 3) != 3) {
fprintf(stderr,
"Error sending response terminator to client\n");
goto close_client_socket; goto close_client_socket;
} }
rlen += n;
}
/* /*
* Close the resource. * Close the resource.
@ -422,6 +391,24 @@ int main(int argc, char *argv[])
goto close_client_socket; goto close_client_socket;
} }
/*
* Terminate and send the response.
*/
if (RBUF_SIZE - rlen < RESP_TERM_LEN) {
fprintf(stderr, "Response buffer is too small");
goto close_client_socket;
}
memcpy(&rbuf[rlen], RESP_TERM, RESP_TERM_LEN);
rlen += RESP_TERM_LEN;
do {
errno = 0;
n = write(cfd, rbuf, rlen);
} while (errno == EINTR);
if (n == -1) {
fprintf(stderr, "Failed to write response to client\n");
goto close_client_socket;
}
close_client_socket: close_client_socket:
close(cfd); close(cfd);
} }