notice 19919

This commit is contained in:
Emil Williams 2024-02-09 21:48:08 +00:00
parent 81eeb80bc8
commit 41c46be8a2
No known key found for this signature in database
GPG Key ID: 5432DB986FDBCF8A
2 changed files with 245 additions and 243 deletions

View File

@ -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: moontalk.rb:
Runs off of ruby, just werks.
You'll need to install ruby to run it. You'll need to install ruby to run it.
See source code for usage. See source code for usage.
moontalk-cli.c:
particually functional, should just werk for normal chatting.
Not as nice for editing text, full NCurses interface.
To compile it, use bake <https://git.lain.church/emil/bake> or just run:
gcc -O2 -std=gnu99 moontalk-cli.c -o moontalk-cli -lncurses -ltinfo
Run -help for usage.
-- GUI Clients --
moontalk.tcl: moontalk.tcl:
Runs off of tcl/tk, just werks.
you'll need tcl and tk to run it. you'll need tcl and tk to run it.
Click the bottom bar to talk. Click the bottom bar to talk.
Graceful about reconnections.
moontalk.c:
Is incomplete, and limited, but is usable.
To compile it, use bake <https://git.lain.church/emil/bake> or just run:
gcc -O2 -std=gnu99 moontalk.c -o moontalk -lncurses -ltinfo
Run -help for further details for usage.

View File

@ -1,10 +1,8 @@
/* moontalk.c - @BAKE cc -O2 -std=gnu99 -Wall -Wextra -Wpedantic -Wno-format-truncation $@ -o $* \ /* moontalk.c - @BAKE cc -O2 -std=gnu99 -Wall -Wextra -Wpedantic -Wno-format-truncation $@ -o $* \
-D_DEFAULT_SOURCE -D_XOPEN_SOURCE=600 -lncurses -ltinfo $+ -D_DEFAULT_SOURCE -D_XOPEN_SOURCE=600 -lncurses -ltinfo $+
* Written by Emil. * Written by Emil.
* Licensed under the GPLv3 only. * Licensed under the GPLv3 only.
* */
* TODO Add proper editing facilities
*/
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
@ -26,6 +24,29 @@
#define SERV "7ks473deh6ggtwqsvbqdurepv5i6iblpbkx33b6cydon3ajph73sssad.onion" #define SERV "7ks473deh6ggtwqsvbqdurepv5i6iblpbkx33b6cydon3ajph73sssad.onion"
#define PORT "50000" #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 TAB 9 /* */
#define BACKSPACE 263 /* ^G */ #define BACKSPACE 263 /* ^G */
@ -38,74 +59,12 @@
#define C_L 12 /* REFRESH */ #define C_L 12 /* REFRESH */
#define C_U 21 /* CLR TO BOL */ #define C_U 21 /* CLR TO BOL */
#define C_W 23 /* DELETE PREVWORD */ #define C_W 23 /* DELETE PREVWORD */
#define C_L 12 /* Signal SIGWINCH */ #define C_L 12 /* Signal full refresh */
#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 void disconnect(void) {
#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 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) {
int sockfd = g_sockfd; int sockfd = g_sockfd;
endwin();
printf("stopping now.\n");
if (sockfd > -1) { close(sockfd); } if (sockfd > -1) { close(sockfd); }
g_sockfd = -1; g_sockfd = -1;
} }
@ -116,7 +75,7 @@ int init_connection(char * serv, char * port) {
struct addrinfo hints, * res; struct addrinfo hints, * res;
memset(&hints, 0, sizeof(struct addrinfo)); memset(&hints, 0, sizeof(struct addrinfo));
hints.ai_family = AF_UNSPEC; hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM; hints.ai_socktype = SOCK_STREAM;
if ((status = getaddrinfo(serv, port, &hints, &res)) != 0) { if ((status = getaddrinfo(serv, port, &hints, &res)) != 0) {
@ -140,215 +99,236 @@ error:
__builtin_unreachable(); __builtin_unreachable();
} }
#if 0 //
int getanonval(char * buf, size_t len) {
return 0;
}
#endif
int countlines(char * buf, size_t len) { void fillline(WINDOW * w, int y, int xstart, char c) {
size_t i = 0; int i = xstart, x = g_x;
for (buf += len - 1; *buf; --buf) for (; i < x; ++i)
{ i += (*buf == '\n'); } { mvwaddch(w,y,i,c); }
return i;
} }
size_t getoff(char * buf, size_t len, size_t count, char c) { void clearline(WINDOW * w, int y) {
size_t i; wmove(w, y, 0);
for (i = 0; count && i < len; ++i) { wclrtoeol(w);
count -= (buf[i] == c) * 1; }
++buf;
void sanitize(char * buf, size_t rem) {
char * base = buf;
buf += rem;
while (buf - base) {
if (*buf < ' ' || *buf > '~') {
if (*buf != '\n')
{ *buf = '!'; }
}
--buf;
} }
return i;
} }
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; }
}
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) { int main (int argc, char ** argv) {
char * argv0 = argv[0]; char * serv = SERV, * port = PORT, name[32] = NAME;
char * serv = SERV, * port = PORT, name[32] = "anonymous";
int sockfd; int sockfd;
{
char * argv0 = argv[0];
while (++argv, --argc) { while (++argv, --argc) {
if (streq(*argv, "-help")) { if (streq(*argv, "-help")) {
printf("%s: HELP\n", argv0); printf(HELP, argv0);
return 1; exit(1);
} }
if (argc - 1) if (argc - 1)
{ --argc; ++argv; } { --argc; ++argv; }
else { else {
printf("%s: %s requires argument\n", argv0, *argv); printf("%s: %s requires argument\n", argv0, *argv);
return 1; return 1;
} }
if (streq(*(argv-1), "-serv")) { if (streq(*(argv-1), "-serv")) {
serv = *argv; serv = *argv;
} } else if (streq(*(argv-1), "-port")) {
else if (streq(*(argv-1), "-port")) { port = *argv;
port = *argv; } else if (streq(*(argv-1), "-name")) {
} memset(name, 0, 31);
else if (streq(*(argv-1), "-name")) { strncpy(name, *argv, 31);
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); initscr();
move(1,0); noecho();
printw("Connecting to %s:%s as %s\n", serv, port, name); keypad(stdscr, ERR);
printw("g_y: %d; g_x: %d\n", g_y, g_x); nodelay(stdscr, TRUE);
refresh(); ESCDELAY = 0;
curs_set(0);
clear(); clear();
atexit(stop); #define WINCOUNT 3
sockfd = init_connection(serv, port); 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 raw[SENDMAX + RECVMAX];
char * sendbuf = raw, * recvbuf = raw + SENDMAX, * off = recvbuf; char * sendbuf = raw, * recvbuf = raw + SENDMAX, * off = recvbuf;
size_t sendminlen; size_t sendminlen, sendlen, recvlen = 0, offlen = recvlen;
size_t sendlen = sendminlen, recvlen = 1, offlen = (g_y - 4) * 255; 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; time_t t;
struct tm * tm; struct tm * tm;
useconds_t frame = 30; useconds_t frame = 30;
useconds_t interval = 1000000 / frame; useconds_t interval = 1000000. / frame;
int32_t ct = 0; int32_t ct;
/* int lc, off; */
int hardrefresh = 0, inputrefresh = 1;
int ch;
int ret;
sendminlen = TIMESTRMAX; int ch, ret;
size_t i;
memcpy(sendbuf + sendminlen, name, strlen(name)); size_t namelen = strlen(name);
sendminlen += strlen(name);
memcpy(sendbuf + sendminlen, "> ", 2);
sendminlen += 2;
sendlen = sendminlen;
decoration(); edit = sendlen = sendminlen = TIMESTRMAX + namelen + 2;
mvaddnstr(g_y - 1, 0, sendbuf, sendlen);
/* fill in the name */
memcpy(sendbuf + TIMESTRMAX, name, namelen);
memcpy(sendbuf + TIMESTRMAX + namelen, "> ", 2);
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) { while (1) {
nextloop: /* input */
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;
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 */
while ((ch = getch()) != -1) { while ((ch = getch()) != -1) {
if (ch == '\n') { if (ch == KEY_RESIZE || ch == C_L) {
if (sendlen == sendminlen) { for (i = 0; i < WINCOUNT; ++i)
continue; { delwin(w[i]); }
} endwin();
if (sendlen + 1 < SENDMAX) erase();
{ sendbuf[sendlen++] = '\n'; } refresh();
if (send(sockfd, sendbuf, sendlen, 0) > 0) { clear();
memcpy(recvbuf + recvlen - 1, sendbuf, (sendlen + recvlen - 1 < RECVMAX) * sendlen); flushinp();
recvlen += sendlen; goto hardrefresh;
hardrefresh = 1;
} else {
mvprintw(g_y - 2, 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)) { else if ((ch > 31 && ch < 127)) {
if (sendlen + 1 < SENDMAX) if (sendlen + 1 < SENDMAX)
{ sendbuf[sendlen++] = ch; } { sendbuf[edit++] = ch; ++sendlen; }
mvaddnstr(g_y - 1, 0, sendbuf, 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, sendbuf, (sendlen + recvlen < RECVMAX) * sendlen);
recvlen += sendlen;
offlen += sendlen;
} else {
mvwprintw(input, 1, 0, "message failed: %s", strerror(errno));
}
/* 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) { else if (ch == BACKSPACE || ch == C_H) {
inputrefresh = 1; inputrefresh = 1;
clearline(g_y - 1); clearline(input, 2);
if (sendlen - 1 >= sendminlen) if (sendlen - 1 >= sendminlen)
{ mvaddch(g_y - 1, --sendlen, ' '); } { mvwaddch(input, 2, --sendlen, ' '); --edit; }
mvaddnstr(g_y - 1, 0, sendbuf, sendlen); mvwaddnstr(input, 2, 0, sendbuf, sendlen);
move(g_y - 1, sendlen); wmove(input, 2, sendlen);
goto nextloop;
} }
else if (ch == C_T) { else if (ch == KEY_LEFT) {
while (*off != '\n') { --off; } /* if (edit > sendminlen) { --edit; } */
if (*off == '\n') { ++off; }
hardrefresh = 1;
} }
else if (ch == C_N) { else if (ch == KEY_RIGHT) {
while (*off != '\n') { ++off; } /* if (edit - 1 < sendlen) { ++edit; } */
}
else if (ch == KEY_DOWN) {
mvwprintw(input, 1, 150, "scroll down %ld", offlen);
while (off - recvbuf < RECVMAX && *off != '\n') { ++off; }
if (*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) { else if (ch == C_W) {
while (sendlen > sendminlen && ispunct(sendbuf[sendlen - 1])) { --sendlen; } while (sendlen > sendminlen && ispunct(sendbuf[sendlen - 1])) { --sendlen; }
while (sendlen > sendminlen && isspace(sendbuf[sendlen - 1])) { --sendlen; } while (sendlen > sendminlen && isspace(sendbuf[sendlen - 1])) { --sendlen; }
while (sendlen > sendminlen && isalnum(sendbuf[sendlen - 1])) { --sendlen; } while (sendlen > sendminlen && isalnum(sendbuf[sendlen - 1])) { --sendlen; }
inputrefresh = 1; inputrefresh = 1;
clearline(g_y - 1); clearline(input, 2);
goto nextloop;
} }
else if (ch == C_L) {
clear(); }
decoration(); /* update and rendering */
hardrefresh = 1; if (ct % frame == 0 || inputrefresh || bodyrefresh) {
ct = 0; UPDATE_TIME();
goto nextloop; /* 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) { if (ret > -1) {
exit(0); 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(); refresh();
for (i = 0; i < WINCOUNT; ++i)
{ wnoutrefresh(w[i]); }
doupdate();
usleep(interval); usleep(interval);
++ct;
} }
return 0;
endwin();
} }