浏览代码

updated clients

master
Emil Williams 3 个月前
父节点
当前提交
3f4161ef04
找不到此签名对应的密钥 GPG 密钥 ID: 5432DB986FDBCF8A
共有 3 个文件被更改,包括 220 次插入97 次删除
  1. +162
    -60
      client/moontalk-cli.c
  2. +43
    -37
      client/moontalk.rb
  3. +15
    -0
      client/moontalk.sh

+ 162
- 60
client/moontalk-cli.c 查看文件

@@ -1,7 +1,11 @@
/* moontalk.c - @BAKE cc -O2 -std=gnu99 -Wall -Wextra -pedantic $@ -o $* -lncurses -ltinfo $+
* Written by Emil.
* Licensed under the GPLv3 only.
*/
/* moontalk.c - @BAKE cc -O2 -std=gnu99 -Wall -Wextra -pedantic -Wno-format-truncation $@ -o $* \
-D_DEFAULT_SOURCE -D_XOPEN_SOURCE=600 -lncurses -ltinfo -lreadline $+
* Written by Emil.
* Licensed under the GPLv3 only.
*
* TODO Add proper editing facilities
* TODO Print sent messages
*/

#include <stdio.h>
#include <stdlib.h>
@@ -18,53 +22,47 @@
#include <netinet/in.h>

#include <ncurses.h>
#include <readline/readline.h>

#define SERV "7ks473deh6ggtwqsvbqdurepv5i6iblpbkx33b6cydon3ajph73sssad.onion"
#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 strneq(a,b,c) (!memcmp(a,b,c))

int g_row, g_col;
int g_y, g_x;
int g_sockfd = -1;

void free_screen(void) {
endwin();
}
void init_screen(int x) {
(void)x;
signal(SIGWINCH, SIG_IGN);

void init_screen(void) {
endwin();
struct winsize w;
ioctl(STDOUT_FILENO, TIOCGWINSZ, &w);
g_y = w.ws_row;
g_x = w.ws_col;
initscr();
cbreak();
noecho();
keypad(stdscr, ERR);
nodelay(stdscr, TRUE);
}

void handle_winch(int x) {
(void)x;
struct winsize w;
signal(SIGWINCH, SIG_IGN);

endwin();
init_screen();
refresh();
clear();

ioctl(STDOUT_FILENO, TIOCGWINSZ, &w);
g_row = w.ws_row;
g_col = w.ws_col;

signal(SIGWINCH, handle_winch);
signal(SIGWINCH, init_screen);
}

int g_sockfd = -1;

void free_connection(void) {
close(g_sockfd);
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 */
@@ -96,15 +94,48 @@ 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;
}

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) {
char * argv0 = argv[0];
char * serv = SERV, * port = PORT, * name = "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;
char * serv = SERV, * port = PORT, name[32] = "anonymous";

int sockfd;

@@ -125,44 +156,115 @@ int main (int argc, char ** argv) {
}
else if (streq(*(argv-1), "-port")) {
printf("port: %s\n", *argv);
port = *argv;
}
else if (streq(*(argv-1), "-name")) {
printf("name: %s\n", *argv);
memset(name, 0, 31);
strncpy(name, *argv, 31);
}
}

atexit(free_screen);
init_screen();
signal(SIGWINCH, handle_winch);
/* atexit(void (*endwin)(void)); */
init_screen(-1);
printw("Connecting to %s:%s as %s\n", serv, port, name);
printw("g_y: %d; g_x: %d\n", g_y, g_x);
refresh();
clear();

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;
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) {
/* 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 */
ch = getch();
if (ch != -1 && ch != '\n') {
sendbuf[sendlen++] = ch;
} else if (ch == '\n') {
t = time(NULL);
tm = gmtime(&t);
strftime(sendbuf - PREFIX_MAX, PREFIX_MAX, "<%Y/%m/%d %H:%M:%S ", tm);
sendbuf[sendlen++] = '\n';
send(sockfd, sendbuf - PREFIX_MAX, sendlen + PREFIX_MAX, 0);
sendlen = 0;
memset(sendbuf, 0, sendlen);
if (ch == -1);
else if (ch == '\n') {
if (sendlen == sendminlen) { continue; }
sendbuf[sendlen++] = '\n'; /* terminator */
send(sockfd, sendbuf, sendlen, 0);
memset(sendbuf + sendminlen, 0, sendlen - sendminlen);
sendlen = sendminlen;
clearline(g_y - 1);
}
/* recv */
recvlen = recv(sockfd, recvbuf, recvmax, MSG_DONTWAIT);
/* render */
clear();
mvaddnstr(0, 0, recvbuf, recvlen);
mvaddnstr(g_row - 1, 0, sendbuf, sendlen);
refresh();
else if (ch == BACKSPACE) {
clearline(g_y - 1);
if (sendlen - 1 >= sendminlen)
{ --sendlen; }
}
else if (ch > 31 && ch < 127) {
if (sendlen + 1 < SENDMAX)
{ sendbuf[sendlen++] = ch; }
}
mvaddnstr(g_y - 1, 0, sendbuf, sendlen);
move(g_y - 1, sendlen);
/* sleep */
++ct;
sleep(interval);
refresh();
}
}

+ 43
- 37
client/moontalk.rb 查看文件

@@ -73,49 +73,55 @@ def main
end
rescue
end
socket = connect
begin
delay = 0
loop do
begin
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("")
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
post(socket, word[1])
else
post(socket, msg)
end
end

read_from(socket)
sleep delay
update_prefix
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
ensure
puts "\nSTOPPING NOW."
socket.close
end
end



+ 15
- 0
client/moontalk.sh 查看文件

@@ -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"

正在加载...
取消
保存