diff options
| author | Mr. Goblin <mrgoblin@mrgoblin.net> | 2026-09-27 22:51:34 +0300 |
|---|---|---|
| committer | Mr. Goblin <mrgoblin@mrgoblin.net> | 2026-09-27 22:51:34 +0300 |
| commit | 76eae6e283c42d1c4a5a0efb94f7d6366d40487b (patch) | |
| tree | fb61705947e7c43212c27b8d87ea323fa201f6ea /btasktd.c | |
| parent | 753621c39b76bd90610ea758567525425f8e2913 (diff) | |
echo server
Diffstat (limited to 'btasktd.c')
| -rw-r--r-- | btasktd.c | 114 |
1 files changed, 98 insertions, 16 deletions
@@ -59,10 +59,26 @@ # define BTASKTD_CLIENT_BUF_SIZE 4096 #endif +#ifndef BTASKTD_MAX_RESPONSE_BUF_SIZE +# define BTASKTD_MAX_RESPONSE_BUF_SIZE 8192 +#endif + +#ifndef BTASKTD_RESPONSE_BUF_SIZE +# define BTASKTD_RESPONSE_BUF_SIZE \ + ((BTASKTD_MAX_RESPONSE_BUF_SIZE) - 256) +#endif + + struct user { int fd; char buf[BTASKTD_CLIENT_BUF_SIZE]; - int bi; + int bi; /* buf index */ +}; + +/* BODY SHOULD BE EMPTY OR END WITH CRLF (\r\n, 13 10) */ +struct response { + int code; + const char *body; /* for empty use NULL or "" */ }; struct btasktd { @@ -96,10 +112,45 @@ find_free_user(const struct user *arr, int count) } static void -send_client(int fd, const char *s) +reset_user_buf(struct user *pu) +{ + pu->bi = 0; + memset(pu->buf, '\0', sizeof(pu->buf)); +} + +static void +reset_user(struct user *pu) +{ + pu->fd = -1; + reset_user_buf(pu); +} + +static void +send_to_client(int fd, const char *s) { int len = strlen(s); - send(fd, s, len, 0); + int code = send(fd, s, len, 0); + if (-1 == code) + perror("send"); +} + +static void +send_response(int fd, struct response r) +{ + char buf[BTASKTD_MAX_RESPONSE_BUF_SIZE] = {0}; + if (NULL == r.body) + r.body = ""; + snprintf(buf, sizeof(buf), "%s%s.\r\n", code_to_str(r.code), + r.body); + send_to_client(fd, buf); +} + +static void +send_response_code(int fd, int code) +{ + struct response r = { CODE_200_OK, NULL }; + r.code = code; + send_response(fd, r); } static void @@ -116,7 +167,7 @@ handle_accept(struct btasktd *this) set_nonblock(fd); idx = find_free_user(this->users, this->users_cnt); if (-1 == idx) { - send_client(fd, CODE_503_STR); + send_response_code(fd, CODE_503_SERVICE_UNAVAILABLE); close(fd); } this->users[idx].fd = fd; @@ -128,17 +179,48 @@ handle_timeout(struct btasktd *this) { } -static int -buf_append(char *buf, int *bi, int bsize, const char *str) +static void +handle_buf(struct btasktd *this, int id, int should_send_response) { - int len = strlen(str); - if (bi + len > bsize) - return -1; + struct response resp; + struct user *pu = &(this->users[id]); + char buf[BTASKTD_RESPONSE_BUF_SIZE] = {0}; + /* dummy yet */ + resp.code = CODE_200_OK; + resp.body = ""; + if (should_send_response) { + snprintf(buf, sizeof(buf), "%s", pu->buf); +#if 1 + send_to_client(pu->fd, buf); +#else + resp.body = buf; + send_response(pu->fd, resp); +#endif + } + reset_user_buf(pu); } static void handle_user(struct btasktd *this, int id) { + int valread; + struct user *pu = &(this->users[id]); + unsigned sz = sizeof(pu->buf) - (pu->bi) - 1; + valread = recv(pu->fd, pu->buf + pu->bi, sz, 0); + if (0 == valread) { + if (pu->bi > 0) { + handle_buf(this, id, 0); + } + close(pu->fd); + reset_user(pu); + return; + } else if (-1 == valread) { + perror("recv"); + close(pu->fd); + reset_user(pu); + return; + } + handle_buf(this, id, 1); } int @@ -232,26 +314,26 @@ main(int argc, char **argv) addr.sin_family = AF_INET; addr.sin_port = htons(port); addr.sin_addr.s_addr = htonl(INADDR_ANY); - res = bind(server_fd, (struct sockaddr*)&addr, sizeof(addr)); + res = setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR, + &opt, sizeof(opt)); if (0 != res) { close(server_fd); free(users); - perror("bind"); + perror("setsockopt"); return 1; } - res = listen(server_fd, BTASKTD_QUEUE_LEN); + res = bind(server_fd, (struct sockaddr*)&addr, sizeof(addr)); if (0 != res) { close(server_fd); free(users); - perror("listen"); + perror("bind"); return 1; } - res = setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR, - &opt, sizeof(opt)); + res = listen(server_fd, BTASKTD_QUEUE_LEN); if (0 != res) { close(server_fd); free(users); - perror("setsockopt"); + perror("listen"); return 1; } |
