From 41c46be8a2bf9d1cfdf5a872287c6e997803aa7a Mon Sep 17 00:00:00 2001 From: Emil Williams Date: Fri, 9 Feb 2024 21:48:08 +0000 Subject: [PATCH] notice 19919 --- client/README | 40 +++- client/moontalk-cli.c | 436 ++++++++++++++++++++---------------------- 2 files changed, 239 insertions(+), 237 deletions(-) diff --git a/client/README b/client/README index 58b234b..3e41023 100644 --- a/client/README +++ b/client/README @@ -1,20 +1,42 @@ -USE moontalk.rb, or moontalk.tcl! +-- "Raw" Clients -- + +The classic: + requires netcat and torify + torify netcat 7ks473deh6ggtwqsvbqdurepv5i6iblpbkx33b6cydon3ajph73sssad.onion 50000 + +The socat: + requires socat and tor daemon + socat - SOCKS4A:127.0.0.1:7ks473deh6ggtwqsvbqdurepv5i6iblpbkx33b6cydon3ajph73sssad.onion:50000,socksport=9050 + +Extension for raw clients: + You can attach rlwrap (readline, bundled seperately) to connect, it'll provide a better experience than going in raw. + Consider using this if your messages ever get split. + +-- CLI Clients -- moontalk.rb: + Runs off of ruby, just werks. + You'll need to install ruby to run it. See source code for usage. -moontalk.tcl: +moontalk-cli.c: - you'll need tcl and tk to run it. - Click the bottom bar to talk. + particually functional, should just werk for normal chatting. + Not as nice for editing text, full NCurses interface. -moontalk.c: + To compile it, use bake or just run: + gcc -O2 -std=gnu99 moontalk-cli.c -o moontalk-cli -lncurses -ltinfo - Is incomplete, and limited, but is usable. + Run -help for usage. - To compile it, use bake or just run: - gcc -O2 -std=gnu99 moontalk.c -o moontalk -lncurses -ltinfo +-- GUI Clients -- + +moontalk.tcl: - Run -help for further details for usage. + Runs off of tcl/tk, just werks. + + you'll need tcl and tk to run it. + Click the bottom bar to talk. + Graceful about reconnections. diff --git a/client/moontalk-cli.c b/client/moontalk-cli.c index f84698f..be68058 100644 --- a/client/moontalk-cli.c +++ b/client/moontalk-cli.c @@ -1,10 +1,8 @@ /* moontalk.c - @BAKE cc -O2 -std=gnu99 -Wall -Wextra -Wpedantic -Wno-format-truncation $@ -o $* \ - -D_DEFAULT_SOURCE -D_XOPEN_SOURCE=600 -lncurses -ltinfo $+ - * Written by Emil. - * Licensed under the GPLv3 only. - * - * TODO Add proper editing facilities - */ + -D_DEFAULT_SOURCE -D_XOPEN_SOURCE=600 -lncurses -ltinfo $+ + * Written by Emil. + * Licensed under the GPLv3 only. + */ #include #include @@ -26,6 +24,29 @@ #define SERV "7ks473deh6ggtwqsvbqdurepv5i6iblpbkx33b6cydon3ajph73sssad.onion" #define PORT "50000" +#define NAME "anonymous" + +#define streq(a,b) (!strcmp(a,b)) +#define strneq(a,b,c) (!memcmp(a,b,c)) + +int g_sockfd; + +#define g_y LINES +#define g_x COLS + +#define HELP \ + "%s [options ...]\n" \ + "\n-serv SERVER Sets the server to connect to [default: " SERV "]" \ + "\n-port PORT Sets the port [default: " PORT "]" \ + "\n-name NAME Sets your display name [default: " NAME "]\n" \ + "\nControls\n" \ + "\nC-l Refreshes the screen" \ + "\nC-w Delete the previous word" \ + "\nC-c Close the client" \ + "\nUp/Down Scrolls all the way up/Scrolls down by a line\n" + + +/* I know, and I don't care */ #define TAB 9 /* */ #define BACKSPACE 263 /* ^G */ @@ -38,74 +59,12 @@ #define C_L 12 /* REFRESH */ #define C_U 21 /* CLR TO BOL */ #define C_W 23 /* DELETE PREVWORD */ -#define C_L 12 /* Signal SIGWINCH */ -#define C_R 18 /* hah not going to implement that */ - -#define C_T 20 /* scroll up */ -#define C_N 14 /* scroll down */ - -#define UP 258 -#define DOWN 259 -#define LEFT 260 -#define RIGHT 261 - -#define TIMESTR "<%Y/%m/%d %H:%M:%S " -#define TIMESTRMAX 21 - -#define SENDMAX (1 << 8) - 1 -#define RECVMAX 17663 /* (1 << 11) */ - -#define streq(a,b) (!strcmp(a,b)) -#define strneq(a,b,c) (!memcmp(a,b,c)) - -#define g_y COLS -#define g_x LINES - -int g_sockfd = -1; - -void fillline(int y, int xstart, char c) { - int i = xstart, x = g_x; - for (; i < x; ++i) - { mvaddch(y,i,c); } -} +#define C_L 12 /* Signal full refresh */ -#define TITLE(str) do { mvprintw(0,0,str); fillline(0,strlen(str),'-'); } while (0) +/****/ -void decoration(void) { - /* mvprintw(g_y - 2, 0, "max screen %d; max ours %d", (g_y - 3) * SENDMAX, RECVMAX); */ - TITLE("-- MOONTALK "); - fillline(g_y - 3, 0, '-'); -} - -#undef TITLE - -int g_hardrefresh = 0; - -void init_screen(int x) { - (void)x; - WINDOW * header, * body, * input; - signal(SIGWINCH, SIG_IGN); - - endwin(); - struct winsize w; - ioctl(STDOUT_FILENO, TIOCGWINSZ, &w); - initscr(); - raw(); - noecho(); - keypad(stdscr, ERR); - nodelay(stdscr, TRUE); - ESCDELAY = 0; - clear(); - decoration(); - g_hardrefresh = 1; - - signal(SIGWINCH, init_screen); -} - -void stop(void) { +void disconnect(void) { int sockfd = g_sockfd; - endwin(); - printf("stopping now.\n"); if (sockfd > -1) { close(sockfd); } g_sockfd = -1; } @@ -116,7 +75,7 @@ int init_connection(char * serv, char * port) { struct addrinfo hints, * res; memset(&hints, 0, sizeof(struct addrinfo)); - hints.ai_family = AF_UNSPEC; + hints.ai_family = AF_UNSPEC; hints.ai_socktype = SOCK_STREAM; if ((status = getaddrinfo(serv, port, &hints, &res)) != 0) { @@ -140,215 +99,236 @@ error: __builtin_unreachable(); } -#if 0 -int getanonval(char * buf, size_t len) { - return 0; -} -#endif +// -int countlines(char * buf, size_t len) { - size_t i = 0; - for (buf += len - 1; *buf; --buf) - { i += (*buf == '\n'); } - return i; +void fillline(WINDOW * w, int y, int xstart, char c) { + int i = xstart, x = g_x; + for (; i < x; ++i) + { mvwaddch(w,y,i,c); } } -size_t getoff(char * buf, size_t len, size_t count, char c) { - size_t i; - for (i = 0; count && i < len; ++i) { - count -= (buf[i] == c) * 1; - ++buf; - } - return i; +void clearline(WINDOW * w, int y) { + wmove(w, y, 0); + wclrtoeol(w); } -size_t lastline(char * buf, size_t len) { - size_t ret; - char * start = buf; - for (buf += len - 1; *buf; --buf) { - ret = (*buf == '\n') ? buf - start : 0; - if (ret) { return ret; } +void sanitize(char * buf, size_t rem) { + char * base = buf; + buf += rem; + while (buf - base) { + if (*buf < ' ' || *buf > '~') { + if (*buf != '\n') + { *buf = '!'; } + } + --buf; } - return 0; -} - -void clearline(int y) { - int oldy, oldx; - getyx(stdscr, oldy, oldx); - move(y, 0); - clrtoeol(); - move(oldy, oldx); } -#define UPDATE_TIME() do { \ - t = time(NULL); \ - tm = gmtime(&t); \ - strftime(sendbuf, TIMESTRMAX, TIMESTR, tm); \ - sendbuf[TIMESTRMAX - 1] = ' '; } while (0) - - int main (int argc, char ** argv) { - char * argv0 = argv[0]; - char * serv = SERV, * port = PORT, name[32] = "anonymous"; - + char * serv = SERV, * port = PORT, name[32] = NAME; int sockfd; + { + char * argv0 = argv[0]; - while (++argv, --argc) { - if (streq(*argv, "-help")) { - printf("%s: HELP\n", argv0); - return 1; - } - if (argc - 1) - { --argc; ++argv; } - else { - printf("%s: %s requires argument\n", argv0, *argv); - return 1; - } - if (streq(*(argv-1), "-serv")) { - serv = *argv; - } - else if (streq(*(argv-1), "-port")) { - port = *argv; - } - else if (streq(*(argv-1), "-name")) { - memset(name, 0, 31); - strncpy(name, *argv, 31); + while (++argv, --argc) { + if (streq(*argv, "-help")) { + printf(HELP, argv0); + exit(1); + } + if (argc - 1) + { --argc; ++argv; } + else { + printf("%s: %s requires argument\n", argv0, *argv); + return 1; + } + if (streq(*(argv-1), "-serv")) { + serv = *argv; + } else if (streq(*(argv-1), "-port")) { + port = *argv; + } else if (streq(*(argv-1), "-name")) { + memset(name, 0, 31); + strncpy(name, *argv, 31); + } } + + printf("Connecting to %s:%s as %s\n", serv, port, name); + + atexit(disconnect); + sockfd = init_connection(serv, port); } - init_screen(-1); - move(1,0); - printw("Connecting to %s:%s as %s\n", serv, port, name); - printw("g_y: %d; g_x: %d\n", g_y, g_x); - refresh(); + initscr(); + noecho(); + keypad(stdscr, ERR); + nodelay(stdscr, TRUE); + ESCDELAY = 0; + curs_set(0); clear(); - atexit(stop); - sockfd = init_connection(serv, port); + #define WINCOUNT 3 + WINDOW * w[WINCOUNT]; + #define header w[0] + #define body w[1] + #define input w[2] + + #define SENDMAX (1 << 8) - 1 + #define RECVMAX 17663 /* (1 << 11) */ char raw[SENDMAX + RECVMAX]; char * sendbuf = raw, * recvbuf = raw + SENDMAX, * off = recvbuf; - size_t sendminlen; - size_t sendlen = sendminlen, recvlen = 1, offlen = (g_y - 4) * 255; + size_t sendminlen, sendlen, recvlen = 0, offlen = recvlen; + size_t edit; + + #define TIMESTR "<%Y/%m/%d %H:%M:%S " + #define TIMESTRMAX 21 + + + #define UPDATE_TIME()\ + do { \ + t = time(NULL); \ + tm = gmtime(&t); \ + strftime(sendbuf, TIMESTRMAX, TIMESTR, tm); \ + sendbuf[TIMESTRMAX - 1] = ' '; \ + } while (0) time_t t; struct tm * tm; + useconds_t frame = 30; - useconds_t interval = 1000000 / frame; - int32_t ct = 0; - /* int lc, off; */ - int hardrefresh = 0, inputrefresh = 1; - int ch; - int ret; + useconds_t interval = 1000000. / frame; + int32_t ct; - sendminlen = TIMESTRMAX; + int ch, ret; + size_t i; - memcpy(sendbuf + sendminlen, name, strlen(name)); - sendminlen += strlen(name); - memcpy(sendbuf + sendminlen, "> ", 2); - sendminlen += 2; - sendlen = sendminlen; + size_t namelen = strlen(name); - decoration(); - mvaddnstr(g_y - 1, 0, sendbuf, sendlen); + edit = sendlen = sendminlen = TIMESTRMAX + namelen + 2; - while (1) { - nextloop: - hardrefresh |= g_hardrefresh; - /* update */ - if (ct % (frame) == 0 || inputrefresh) { - UPDATE_TIME(); - mvaddnstr(g_y - 1, 0, sendbuf, sendlen); - } - /* recv */ - if (ct % (frame * 2) == 0) { - ret = recv(sockfd, recvbuf + recvlen - 1, RECVMAX - recvlen + 1, MSG_DONTWAIT); - mvprintw(g_y - 2, 150, "ct:%d:%d:called", ct, ret); - if (ret > -1) { - recvlen += ret; + /* fill in the name */ + memcpy(sendbuf + TIMESTRMAX, name, namelen); + memcpy(sendbuf + TIMESTRMAX + namelen, "> ", 2); - mvprintw(g_y - 2, 50, "rendstat ct:%d:%d:%ld", ct, ret, recvlen); - if (ret > 0 && recvbuf[recvlen-1] == '\n') { - mvprintw(g_y - 2, 0, "newline at %ld", recvlen-1); - } - mvprintw(g_y - 2, 130, "ct:%d:rendered", ct); - hardrefresh = 1; - } - } - if (hardrefresh) { - mvprintw(g_y - 2, 100, "ct:%d:REFRESH INVOKED", ct); - mvaddnstr(1, 0, off, offlen); - hardrefresh = 0; - g_hardrefresh = 0; - } - /* send */ + int inputrefresh, bodyrefresh; + +hardrefresh: + ct = 0; + inputrefresh = bodyrefresh = 1; + + header = newwin(1, g_x, 0, 0); + body = newwin(g_y - 4, g_x, 1, 0); + input = newwin(3, g_x, g_y - 3, 0); + + fillline(header, 0, 0, '-'); + mvwprintw(header, 0, 2, " moontalk "); + fillline(input, 0, 0, '-'); + + while (1) { + /* input */ while ((ch = getch()) != -1) { - if (ch == '\n') { - if (sendlen == sendminlen) { - continue; - } + if (ch == KEY_RESIZE || ch == C_L) { + for (i = 0; i < WINCOUNT; ++i) + { delwin(w[i]); } + endwin(); + erase(); + refresh(); + clear(); + flushinp(); + goto hardrefresh; + } + else if ((ch > 31 && ch < 127)) { + if (sendlen + 1 < SENDMAX) + { sendbuf[edit++] = ch; ++sendlen; } + /* mvwchgat(input, 2, sendlen - 1, 1, A_REVERSE, 0, NULL); */ + mvwaddnstr(input, 2, 0, sendbuf, sendlen); + } + else if (ch == '\n') { + if (sendlen == sendminlen) + { continue; } if (sendlen + 1 < SENDMAX) { sendbuf[sendlen++] = '\n'; } if (send(sockfd, sendbuf, sendlen, 0) > 0) { - memcpy(recvbuf + recvlen - 1, sendbuf, (sendlen + recvlen - 1 < RECVMAX) * sendlen); + memcpy(recvbuf + recvlen, sendbuf, (sendlen + recvlen < RECVMAX) * sendlen); recvlen += sendlen; - hardrefresh = 1; + offlen += sendlen; } else { - mvprintw(g_y - 2, 0, "message failed: %s", strerror(errno)); + mvwprintw(input, 1, 0, "message failed: %s", strerror(errno)); } - mvaddch(g_y - 1, sendminlen, ' '); - inputrefresh = 1; - clearline(g_y - 1); - sendlen = sendminlen; - } - else if ((ch > 31 && ch < 127)) { - if (sendlen + 1 < SENDMAX) - { sendbuf[sendlen++] = ch; } - mvaddnstr(g_y - 1, 0, sendbuf, sendlen); + /* mvwaddch(0, sendminlen, ' '); */ + /* mvwchgat(input, 2, 0, 1, A_STANDOUT, 0, NULL); */ + bodyrefresh = inputrefresh = 1; + clearline(input, 2); + edit = sendlen = sendminlen; } else if (ch == BACKSPACE || ch == C_H) { inputrefresh = 1; - clearline(g_y - 1); + clearline(input, 2); if (sendlen - 1 >= sendminlen) - { mvaddch(g_y - 1, --sendlen, ' '); } - mvaddnstr(g_y - 1, 0, sendbuf, sendlen); - move(g_y - 1, sendlen); - goto nextloop; + { mvwaddch(input, 2, --sendlen, ' '); --edit; } + mvwaddnstr(input, 2, 0, sendbuf, sendlen); + wmove(input, 2, sendlen); } - else if (ch == C_T) { - while (*off != '\n') { --off; } - if (*off == '\n') { ++off; } - hardrefresh = 1; + else if (ch == KEY_LEFT) { + /* if (edit > sendminlen) { --edit; } */ + } + else if (ch == KEY_RIGHT) { + /* if (edit - 1 < sendlen) { ++edit; } */ } - else if (ch == C_N) { - while (*off != '\n') { ++off; } + else if (ch == KEY_DOWN) { + mvwprintw(input, 1, 150, "scroll down %ld", offlen); + while (off - recvbuf < RECVMAX && *off != '\n') { ++off; } if (*off == '\n') { ++off; } - hardrefresh = 1; + wclear(body); + bodyrefresh = 1; + } + else if (ch == KEY_UP) { + mvwprintw(input, 1, 150, "scroll up %ld", offlen); + while (off - recvbuf > 0) { --off; } + /* wclear(body); */ + bodyrefresh = 1; } else if (ch == C_W) { while (sendlen > sendminlen && ispunct(sendbuf[sendlen - 1])) { --sendlen; } while (sendlen > sendminlen && isspace(sendbuf[sendlen - 1])) { --sendlen; } while (sendlen > sendminlen && isalnum(sendbuf[sendlen - 1])) { --sendlen; } inputrefresh = 1; - clearline(g_y - 1); - goto nextloop; + clearline(input, 2); } - else if (ch == C_L) { - clear(); - decoration(); - hardrefresh = 1; - ct = 0; - goto nextloop; + + } + /* update and rendering */ + if (ct % frame == 0 || inputrefresh || bodyrefresh) { + UPDATE_TIME(); + /* wclear(input); */ + mvwaddnstr(input, 2, 0, sendbuf, sendlen); + + ret = recv(sockfd, recvbuf + recvlen, RECVMAX - recvlen, MSG_DONTWAIT); + if (errno != EAGAIN) + { mvwaddstr(input, 1, 0, strerror(errno)); } + if (bodyrefresh) { + bodyrefresh = 0; + if (!(ret > -1)) + goto _bodyrefresh; } - else if (ch == C_D) { - exit(0); + if (ret > -1) { + sanitize(recvbuf + recvlen, ret); + if (ret + recvlen < RECVMAX) + { + recvlen += ret; + offlen += ret; + } + _bodyrefresh: + mvwprintw(input, 1, 50, "render ct:%d ret:%d", ct, ret); + mvwaddnstr(body, 0,0, off, offlen); } } - /* frame update */ - move(g_y - 1, sendlen); - ++ct; refresh(); + for (i = 0; i < WINCOUNT; ++i) + { wnoutrefresh(w[i]); } + doupdate(); usleep(interval); + ++ct; } - return 0; + + endwin(); } -- 2.39.5