updated clients
This commit is contained in:
parent
47738e21ae
commit
3f4161ef04
@ -1,7 +1,11 @@
|
|||||||
/* moontalk.c - @BAKE cc -O2 -std=gnu99 -Wall -Wextra -pedantic $@ -o $* -lncurses -ltinfo $+
|
/* moontalk.c - @BAKE cc -O2 -std=gnu99 -Wall -Wextra -pedantic -Wno-format-truncation $@ -o $* \
|
||||||
* Written by Emil.
|
-D_DEFAULT_SOURCE -D_XOPEN_SOURCE=600 -lncurses -ltinfo -lreadline $+
|
||||||
* Licensed under the GPLv3 only.
|
* Written by Emil.
|
||||||
*/
|
* Licensed under the GPLv3 only.
|
||||||
|
*
|
||||||
|
* TODO Add proper editing facilities
|
||||||
|
* TODO Print sent messages
|
||||||
|
*/
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
@ -18,53 +22,47 @@
|
|||||||
#include <netinet/in.h>
|
#include <netinet/in.h>
|
||||||
|
|
||||||
#include <ncurses.h>
|
#include <ncurses.h>
|
||||||
|
#include <readline/readline.h>
|
||||||
|
|
||||||
#define SERV "7ks473deh6ggtwqsvbqdurepv5i6iblpbkx33b6cydon3ajph73sssad.onion"
|
#define SERV "7ks473deh6ggtwqsvbqdurepv5i6iblpbkx33b6cydon3ajph73sssad.onion"
|
||||||
#define PORT "50000"
|
#define PORT "50000"
|
||||||
|
|
||||||
|
#define BACKSPACE 263 /* ^G */
|
||||||
|
|
||||||
|
#define TIMESTR "<%Y/%m/%d %H:%M:%S "
|
||||||
|
#define TIMESTRMAX 21
|
||||||
|
|
||||||
|
#define SENDMAX (1 << 8) - 1
|
||||||
|
#define RECVMAX (1 << 11)
|
||||||
|
|
||||||
#define streq(a,b) (!strcmp(a,b))
|
#define streq(a,b) (!strcmp(a,b))
|
||||||
|
#define strneq(a,b,c) (!memcmp(a,b,c))
|
||||||
|
|
||||||
int g_row, g_col;
|
int g_y, g_x;
|
||||||
|
int g_sockfd = -1;
|
||||||
|
|
||||||
|
void init_screen(int x) {
|
||||||
|
(void)x;
|
||||||
|
signal(SIGWINCH, SIG_IGN);
|
||||||
|
|
||||||
void free_screen(void) {
|
|
||||||
endwin();
|
endwin();
|
||||||
}
|
struct winsize w;
|
||||||
|
ioctl(STDOUT_FILENO, TIOCGWINSZ, &w);
|
||||||
void init_screen(void) {
|
g_y = w.ws_row;
|
||||||
|
g_x = w.ws_col;
|
||||||
initscr();
|
initscr();
|
||||||
cbreak();
|
cbreak();
|
||||||
noecho();
|
noecho();
|
||||||
keypad(stdscr, ERR);
|
keypad(stdscr, ERR);
|
||||||
nodelay(stdscr, TRUE);
|
nodelay(stdscr, TRUE);
|
||||||
}
|
|
||||||
|
|
||||||
void handle_winch(int x) {
|
|
||||||
(void)x;
|
|
||||||
struct winsize w;
|
|
||||||
signal(SIGWINCH, SIG_IGN);
|
|
||||||
|
|
||||||
endwin();
|
|
||||||
init_screen();
|
|
||||||
refresh();
|
|
||||||
clear();
|
clear();
|
||||||
|
|
||||||
ioctl(STDOUT_FILENO, TIOCGWINSZ, &w);
|
signal(SIGWINCH, init_screen);
|
||||||
g_row = w.ws_row;
|
|
||||||
g_col = w.ws_col;
|
|
||||||
|
|
||||||
signal(SIGWINCH, handle_winch);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int g_sockfd = -1;
|
|
||||||
|
|
||||||
void free_connection(void) {
|
void free_connection(void) {
|
||||||
close(g_sockfd);
|
close(g_sockfd);
|
||||||
g_sockfd = -1;
|
g_sockfd = -1;
|
||||||
|
|
||||||
/* the program should be at an end. If we're reconnecting, then at
|
|
||||||
the top level (main) we'd free, even though the main's sockfd is now
|
|
||||||
out-of-date, we can simply ignore that and take the result of socket
|
|
||||||
init */
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* always returns an accessible socket */
|
/* always returns an accessible socket */
|
||||||
@ -96,15 +94,48 @@ error:
|
|||||||
__builtin_unreachable();
|
__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;
|
||||||
|
}
|
||||||
|
|
||||||
|
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 x = g_x;
|
||||||
|
int oldy, oldx;
|
||||||
|
getyx(stdscr, oldy, oldx);
|
||||||
|
move(y, x);
|
||||||
|
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 * argv0 = argv[0];
|
||||||
char * serv = SERV, * port = PORT, * name = "anonymous";
|
char * serv = SERV, * port = PORT, name[32] = "anonymous";
|
||||||
|
|
||||||
#define PREFIX_MAX 21
|
|
||||||
char raw[(2 << 9) + (2 << 13)];
|
|
||||||
char * sendbuf = raw + PREFIX_MAX, * recvbuf = raw + (2 << 9);
|
|
||||||
size_t sendlen = 0, sendmax = (2 << 9) - PREFIX_MAX,
|
|
||||||
recvlen = 0, recvmax = 2 << 13;
|
|
||||||
|
|
||||||
int sockfd;
|
int sockfd;
|
||||||
|
|
||||||
@ -125,44 +156,115 @@ int main (int argc, char ** argv) {
|
|||||||
}
|
}
|
||||||
else if (streq(*(argv-1), "-port")) {
|
else if (streq(*(argv-1), "-port")) {
|
||||||
printf("port: %s\n", *argv);
|
printf("port: %s\n", *argv);
|
||||||
|
port = *argv;
|
||||||
}
|
}
|
||||||
else if (streq(*(argv-1), "-name")) {
|
else if (streq(*(argv-1), "-name")) {
|
||||||
printf("name: %s\n", *argv);
|
printf("name: %s\n", *argv);
|
||||||
|
memset(name, 0, 31);
|
||||||
|
strncpy(name, *argv, 31);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
atexit(free_screen);
|
/* atexit(void (*endwin)(void)); */
|
||||||
init_screen();
|
init_screen(-1);
|
||||||
signal(SIGWINCH, handle_winch);
|
|
||||||
printw("Connecting to %s:%s as %s\n", serv, port, name);
|
printw("Connecting to %s:%s as %s\n", serv, port, name);
|
||||||
|
printw("g_y: %d; g_x: %d\n", g_y, g_x);
|
||||||
refresh();
|
refresh();
|
||||||
|
clear();
|
||||||
|
|
||||||
sockfd = init_connection(serv, port);
|
sockfd = init_connection(serv, port);
|
||||||
float interval = 1 / 30;
|
|
||||||
int ch;
|
char raw[SENDMAX + RECVMAX];
|
||||||
|
char * sendbuf = raw, * recvbuf = raw + SENDMAX;
|
||||||
|
size_t sendminlen;
|
||||||
|
size_t sendlen = sendminlen, recvlen = 0;
|
||||||
|
|
||||||
time_t t;
|
time_t t;
|
||||||
struct tm * tm;
|
struct tm * tm;
|
||||||
|
int frame = 15.;
|
||||||
|
float interval = 1. / frame;
|
||||||
|
int32_t ct = 0;
|
||||||
|
int ch;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
sendminlen = TIMESTRMAX;
|
||||||
|
UPDATE_TIME();
|
||||||
|
|
||||||
|
memcpy(sendbuf + sendminlen, name, strlen(name));
|
||||||
|
sendminlen += strlen(name);
|
||||||
|
memcpy(sendbuf + sendminlen, "> ", 2);
|
||||||
|
sendminlen += 2;
|
||||||
|
sendlen = sendminlen;
|
||||||
|
|
||||||
|
rl_bind_key('\t', rl_insert);
|
||||||
|
rl_catch_signals = 0;
|
||||||
|
rl_catch_sigwinch = 0;
|
||||||
|
rl_prep_term_function = NULL;
|
||||||
|
rl_deprep_term_function = NULL;
|
||||||
|
rl_change_environment = 0;
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
rl_getc_function = +[](FILE* ignore){
|
||||||
|
input_available = false;
|
||||||
|
return (int)input;
|
||||||
|
};
|
||||||
|
rl_input_available_hook = +[]{
|
||||||
|
return input_available;
|
||||||
|
};
|
||||||
|
rl_redisplay_function = +[]{
|
||||||
|
wmove(myWindow, 1, 1);
|
||||||
|
wclrtoeol(myWindow);
|
||||||
|
box(myWindow, 0, 0);
|
||||||
|
waddstr(myWindow, rl_line_buffer);
|
||||||
|
wrefresh(myWindow);
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
rl_callback_handler_install("", +[](char *line){
|
||||||
|
wmove(stdscr, 0, 0);
|
||||||
|
wclrtoeol(stdscr);
|
||||||
|
addstr(line);
|
||||||
|
refresh();
|
||||||
|
return;
|
||||||
|
});
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
|
/* update */
|
||||||
|
if (ct % frame == 0) {
|
||||||
|
UPDATE_TIME();
|
||||||
|
}
|
||||||
|
if (ct % (frame * 2) == 0) {
|
||||||
|
ret = recv(sockfd, recvbuf + recvlen, RECVMAX - recvlen, MSG_DONTWAIT);
|
||||||
|
recvlen += (ret > 0) * ret;
|
||||||
|
mvaddnstr(0, 0, recvbuf, recvlen);
|
||||||
|
mvprintw(g_y - 2, 0, "recvlen %ld", recvlen);
|
||||||
|
}
|
||||||
/* send */
|
/* send */
|
||||||
ch = getch();
|
ch = getch();
|
||||||
if (ch != -1 && ch != '\n') {
|
if (ch == -1);
|
||||||
sendbuf[sendlen++] = ch;
|
else if (ch == '\n') {
|
||||||
} else if (ch == '\n') {
|
if (sendlen == sendminlen) { continue; }
|
||||||
t = time(NULL);
|
sendbuf[sendlen++] = '\n'; /* terminator */
|
||||||
tm = gmtime(&t);
|
send(sockfd, sendbuf, sendlen, 0);
|
||||||
strftime(sendbuf - PREFIX_MAX, PREFIX_MAX, "<%Y/%m/%d %H:%M:%S ", tm);
|
memset(sendbuf + sendminlen, 0, sendlen - sendminlen);
|
||||||
sendbuf[sendlen++] = '\n';
|
sendlen = sendminlen;
|
||||||
send(sockfd, sendbuf - PREFIX_MAX, sendlen + PREFIX_MAX, 0);
|
clearline(g_y - 1);
|
||||||
sendlen = 0;
|
|
||||||
memset(sendbuf, 0, sendlen);
|
|
||||||
}
|
}
|
||||||
/* recv */
|
else if (ch == BACKSPACE) {
|
||||||
recvlen = recv(sockfd, recvbuf, recvmax, MSG_DONTWAIT);
|
clearline(g_y - 1);
|
||||||
/* render */
|
if (sendlen - 1 >= sendminlen)
|
||||||
clear();
|
{ --sendlen; }
|
||||||
mvaddnstr(0, 0, recvbuf, recvlen);
|
}
|
||||||
mvaddnstr(g_row - 1, 0, sendbuf, sendlen);
|
else if (ch > 31 && ch < 127) {
|
||||||
refresh();
|
if (sendlen + 1 < SENDMAX)
|
||||||
|
{ sendbuf[sendlen++] = ch; }
|
||||||
|
}
|
||||||
|
mvaddnstr(g_y - 1, 0, sendbuf, sendlen);
|
||||||
|
move(g_y - 1, sendlen);
|
||||||
/* sleep */
|
/* sleep */
|
||||||
|
++ct;
|
||||||
sleep(interval);
|
sleep(interval);
|
||||||
|
refresh();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -73,49 +73,55 @@ def main
|
|||||||
end
|
end
|
||||||
rescue
|
rescue
|
||||||
end
|
end
|
||||||
socket = connect
|
loop do
|
||||||
begin
|
begin
|
||||||
delay = 0
|
socket = connect
|
||||||
|
delay = 0
|
||||||
|
|
||||||
h = { "BYE" => 1, "QUIT" => 1, "SAY" => 2, "CLEAR" => 3, "NICK" => 4, "RECONNECT" => 5, "DELAY" => 6 }
|
h = { "BYE" => 1, "QUIT" => 1, "SAY" => 2, "CLEAR" => 3, "NAME" => 4, "NICK" => 4,
|
||||||
|
"RC" => 5, "RECONNECT" => 5, "DELAY" => 6 }
|
||||||
|
|
||||||
update_prefix
|
|
||||||
while msg = Readline.readline(@prefix, true)
|
|
||||||
if not msg.empty?
|
|
||||||
msg.strip!
|
|
||||||
word = msg.split(/^([\w]*)$|^([\w]*) (.*)$/)[1..]
|
|
||||||
case h[word[0]]
|
|
||||||
when h["BYE"]
|
|
||||||
post(socket, "BYE")
|
|
||||||
exit 0
|
|
||||||
when h["CLEAR"]
|
|
||||||
puts "\e[1;1H\e[2J"
|
|
||||||
when h["NICK"]
|
|
||||||
if not word[1].empty?
|
|
||||||
@name = word[1]
|
|
||||||
end
|
|
||||||
when h["RECONNECT"]
|
|
||||||
socket.close
|
|
||||||
socket = connect
|
|
||||||
when h["DELAY"]
|
|
||||||
delay = word[1].to_i
|
|
||||||
when h["SAY"]
|
|
||||||
if not word.length > 1
|
|
||||||
word.push("")
|
|
||||||
end
|
|
||||||
post(socket, word[1])
|
|
||||||
else
|
|
||||||
post(socket, msg)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
read_from(socket)
|
|
||||||
sleep delay
|
|
||||||
update_prefix
|
update_prefix
|
||||||
|
while msg = Readline.readline(@prefix, true)
|
||||||
|
if not msg.empty?
|
||||||
|
msg.strip!
|
||||||
|
word = msg.split(/^\/([\w]*)$|^([\w]*) (.*)$/)[1..]
|
||||||
|
case h[word[0]]
|
||||||
|
when h["BYE"]
|
||||||
|
post(socket, "BYE")
|
||||||
|
exit 0
|
||||||
|
when h["CLEAR"]
|
||||||
|
puts "\e[1;1H\e[2J"
|
||||||
|
when h["NICK"]
|
||||||
|
if not word[1].empty?
|
||||||
|
@name = word[1]
|
||||||
|
end
|
||||||
|
when h["RC"]
|
||||||
|
puts "reconnecting..."
|
||||||
|
socket.close
|
||||||
|
socket = connect
|
||||||
|
when h["DELAY"]
|
||||||
|
delay = word[1].to_i
|
||||||
|
when h["SAY"]
|
||||||
|
if not word.length > 1
|
||||||
|
word.push("")
|
||||||
|
end
|
||||||
|
post(socket, word[1])
|
||||||
|
else
|
||||||
|
post(socket, msg)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
read_from(socket)
|
||||||
|
sleep delay
|
||||||
|
update_prefix
|
||||||
|
end
|
||||||
|
rescue (Errno::ECONNREFUSED Errno::EPIPE)
|
||||||
|
puts "\n THE HOUSE IS ON FIRE."
|
||||||
|
ensure
|
||||||
|
puts "\nSTOPPING NOW."
|
||||||
|
exit 1
|
||||||
end
|
end
|
||||||
ensure
|
|
||||||
puts "\nSTOPPING NOW."
|
|
||||||
socket.close
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
15
client/moontalk.sh
Normal file
15
client/moontalk.sh
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
# add this to your .bashrc
|
||||||
|
|
||||||
|
# socat has a more reliable connection to the server than torify, it seems
|
||||||
|
|
||||||
|
# if you want a more reliable client that isn't socat, run:
|
||||||
|
|
||||||
|
# socat TCP-LISTEN:22222 SOCKS4a:localhost:7ks473deh6ggtwqsvbqdurepv5i6iblpbkx33b6cydon3ajph73sssad.onion:50000,socksport=9050 &
|
||||||
|
# nc localhost 22222
|
||||||
|
# ruby moontalk.rb -serv localhost -port 22222
|
||||||
|
|
||||||
|
# or any other client with the server localhost and port 22222.
|
||||||
|
|
||||||
|
# tail -1 moontalk.sh >> ~/.bashrc
|
||||||
|
alias socat_moontalk="socat STDIO SOCKS4A:localhost:7ks473deh6ggtwqsvbqdurepv5i6iblpbkx33b6cydon3ajph73sssad.onion:50000,socksport=9150"
|
Loading…
Reference in New Issue
Block a user