diff options
| -rw-r--r-- | PROTOCOL | 11 | ||||
| -rw-r--r-- | README | 2 | ||||
| -rw-r--r-- | btasktd.c | 152 | ||||
| -rw-r--r-- | codes.h | 19 |
4 files changed, 165 insertions, 19 deletions
diff --git a/PROTOCOL b/PROTOCOL new file mode 100644 index 0000000..9abf559 --- /dev/null +++ b/PROTOCOL @@ -0,0 +1,11 @@ +------------------------------------------------------------------------- +ANSWER CODES +------------------------------------------------------------------------- +200 OK +201 Created +400 Bad request +401 Unauthorized +403 Forbidden +404 Not found +409 Conflict +503 Service unavailable @@ -4,7 +4,7 @@ Copyright (c) 2026, Mr. Goblin Licensed under terms of BSD 2-Clause License ========================================================================= -Lightweight, fast and free daemon for task tracking. +Lightweight, fast and free server for task tracking. Written in limited C99 (almost in C89), builds statically. @@ -40,12 +40,13 @@ #include <unistd.h> #include <errno.h> #include "cliflags.h" +#include "codes.h" #define BTASKTD_HELP_STR \ "Copyright (c) 2026, Mr. Goblin\n" \ "btasktd - task tracking TCP-server\n" \ "Usage: btasktd [-Vh] [-p port] [-u users]\n" \ - "For more info read program's man page\n" + "For more info read the program's man page\n" #define BTASKTD_VERSION_STR \ "0.0.0" @@ -54,10 +55,26 @@ # define BTASKTD_QUEUE_LEN 16 #endif +#ifndef BTASKTD_CLIENT_BUF_SIZE +# define BTASKTD_CLIENT_BUF_SIZE 4096 +#endif + +struct user { + int fd; + char buf[BTASKTD_CLIENT_BUF_SIZE]; + int bi; +}; + +struct btasktd { + int fd; + int users_cnt; + struct user *users; +}; + static void fprint_help(FILE *f) { - fputs(BTASKTD_HELP_STR, f); + fprintf(f, "%s", BTASKTD_HELP_STR); } static void @@ -67,23 +84,84 @@ set_nonblock(int fd) fcntl(fd, F_SETFL, fflags|O_NONBLOCK); } +static int +find_free_user(const struct user *arr, int count) +{ + int i; + for (i = 0; i < count; i++) { + if (-1 == arr[i].fd) + return i; + } + return -1; +} + +static void +send_client(int fd, const char *s) +{ + int len = strlen(s); + send(fd, s, len, 0); +} + +static void +handle_accept(struct btasktd *this) +{ + int idx; + struct sockaddr_in user_addr = {0}; + socklen_t addrlen = sizeof(user_addr); + int fd = accept(this->fd, (struct sockaddr*)&user_addr, &addrlen); + if (-1 == fd) { + perror("accept"); + return; + } + set_nonblock(fd); + idx = find_free_user(this->users, this->users_cnt); + if (-1 == idx) { + send_client(fd, CODE_503_STR); + close(fd); + } + this->users[idx].fd = fd; + this->users[idx].bi = 0; +} + +static void +handle_timeout(struct btasktd *this) +{ +} + +static int +buf_append(char *buf, int *bi, int bsize, const char *str) +{ + int len = strlen(str); + if (bi + len > bsize) + return -1; +} + +static void +handle_user(struct btasktd *this, int id) +{ +} + int main(int argc, char **argv) { + struct btasktd server; int server_fd, opt = 1, res, port, passed_flags = 1, users_cnt; - int *users = NULL; + int max_fd; + struct user *users = NULL; + int i; struct sockaddr_in addr = {0}; struct int_flag_val int_res; - struct bool_flag_val show_ver, show_help; + struct bool_flag_val bool_res; + fd_set readfds; - show_ver = extract_bool_flag('V', argc, argv); - if (fvr_ok == show_ver.code && show_ver.data) { + bool_res = extract_bool_flag('V', argc, argv); + if (fvr_ok == bool_res.code && bool_res.data) { printf("btasktd version %s\n", BTASKTD_VERSION_STR); return 0; } - show_help = extract_bool_flag('h', argc, argv); - if (fvr_ok == show_help.code && show_help.data) { + bool_res = extract_bool_flag('h', argc, argv); + if (fvr_ok == bool_res.code && bool_res.data) { fprint_help(stdout); return 0; } @@ -94,17 +172,17 @@ main(int argc, char **argv) # ifdef BTASKTD_DEFAULT_PORT port = BTASKTD_DEFAULT_PORT; # else - fputs("No port specified!\n", stderr); + fprintf(stderr, "No port specified!\n"); passed_flags = 0; # endif break; case fvr_ok: port = int_res.data; - if (port < 0) + if (port > 0) break; /* fallthrough */ case fvr_invalid: - fputs("Invalid port!\n", stderr); + fprintf(stderr, "Invalid port!\n"); return 1; break; } @@ -115,32 +193,35 @@ main(int argc, char **argv) # ifdef BTASKTD_DEFAULT_USERS_CNT users_cnt = BTASKTD_DEFAULT_USERS_CNT; # else - fputs("No users count specified!\n", stderr); + fprintf(stderr, "No users count specified!\n"); passed_flags = 0; # endif break; case fvr_ok: users_cnt = int_res.data; - if (users_cnt <= 0) + if (users_cnt > 0) break; /* fallthrough */ case fvr_invalid: - fputs("Invalid users count!\n", stderr); + fprintf(stderr, "Invalid users count!\n"); return 1; break; } if (!passed_flags) { - fputs("-\n", stderr); + fprintf(stderr, "-\n"); fprint_help(stderr); return 1; } - users = (int*)malloc(users_cnt * sizeof(int)); + users = (struct user*)calloc(users_cnt, sizeof(struct user)); if (NULL == users) { - fputs("No memory!\n", stderr); + fprintf(stderr, "No memory!\n"); return 1; } + for (i = 0; i < users_cnt; i++) { + users[i].fd = -1; + } server_fd = socket(AF_INET, SOCK_STREAM, 0); if (server_fd < 0) { @@ -175,9 +256,44 @@ main(int argc, char **argv) } set_nonblock(server_fd); + + server.fd = server_fd; + server.users_cnt = users_cnt; + server.users = users; printf("btaskt server btasktd started on port %d\n", port); - /* main loop here */ + for (;;) { + FD_ZERO(&readfds); + FD_SET(server_fd, &readfds); + max_fd = server_fd; + for (i = 0; i < users_cnt; i++) { + if (-1 == users[i].fd) + continue; + FD_SET(users[i].fd, &readfds); + if (users[i].fd > max_fd) + max_fd = users[i].fd; + } + res = select(max_fd+1, &readfds, NULL, NULL, NULL); + if (-1 == res) { + if (EINTR == errno) { + /* signal handler called */ + } else { + perror("select"); + } + continue; + } else if (0 == res) { + handle_timeout(&server); + continue; + } + if (FD_ISSET(server_fd, &readfds)) + handle_accept(&server); + for (i = 0; i < users_cnt; i++) { + if (-1 == users[i].fd) + continue; + if (FD_ISSET(users[i].fd, &readfds)) + handle_user(&server, i); + } + } printf("btaskt server btasktd stopped\n"); close(server_fd); @@ -0,0 +1,19 @@ +#ifndef _H_SENTRY +#define _H_SENTRY +#ifdef __cplusplus +extern "C" { +#endif + +#define CODE_200_STR "OK" +#define CODE_201_STR "Created" +#define CODE_400_STR "Bad request" +#define CODE_401_STR "Unauthorized" +#define CODE_403_STR "Forbidden" +#define CODE_404_STR "Not found" +#define CODE_409_STR "Conflict" +#define CODE_503_STR "Service unavailable" + +#ifdef __cplusplus +} +#endif +#endif /* _H_SENTRY */ |
