aboutsummaryrefslogtreecommitdiff
path: root/btasktd.c
diff options
context:
space:
mode:
authorMr. Goblin <mrgoblin@mrgoblin.net>2026-09-27 22:51:34 +0300
committerMr. Goblin <mrgoblin@mrgoblin.net>2026-09-27 22:51:34 +0300
commit76eae6e283c42d1c4a5a0efb94f7d6366d40487b (patch)
treefb61705947e7c43212c27b8d87ea323fa201f6ea /btasktd.c
parent753621c39b76bd90610ea758567525425f8e2913 (diff)
echo server
Diffstat (limited to 'btasktd.c')
-rw-r--r--btasktd.c114
1 files changed, 98 insertions, 16 deletions
diff --git a/btasktd.c b/btasktd.c
index 6abb00c..75af779 100644
--- a/btasktd.c
+++ b/btasktd.c
@@ -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;
}