]> git.xolatile.top Git - public-moontalk.git/commitdiff
update clients further, more usable state
authorEmil Williams <emilwilliams@tuta.io>
Tue, 6 Feb 2024 03:17:23 +0000 (03:17 +0000)
committerEmil Williams <emilwilliams@tuta.io>
Tue, 6 Feb 2024 03:17:23 +0000 (03:17 +0000)
client/README
client/moontalk-cli.c
server/blackhole/blackhole.c [new file with mode: 0644]

index 7834c5dea1cb692869fcaa7b54d275690e9f6621..58b234b0696142eefdbcb6088da8e8c514a4c726 100644 (file)
@@ -12,7 +12,7 @@ moontalk.tcl:
 
 moontalk.c:
 
-  IS INCOMPLETE, do not use it.
+  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
index 57c1f946708262e9eff694ad23b54fb68de58330..37b2dd9f03889941cbb0c7a252f519a12af78c83 100644 (file)
@@ -1,11 +1,10 @@
-/* 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
-   */
+/* 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
+ */
 
 #include <stdio.h>
 #include <stdlib.h>
@@ -13,6 +12,7 @@
 #include <unistd.h>
 #include <signal.h>
 #include <time.h>
+#include <errno.h>
 
 #include <sys/ioctl.h>
 #include <sys/types.h>
 #include <netinet/in.h>
 
 #include <ncurses.h>
-#include <readline/readline.h>
 
 #define SERV "7ks473deh6ggtwqsvbqdurepv5i6iblpbkx33b6cydon3ajph73sssad.onion"
 #define PORT "50000"
 
+#define TAB 9 /*        */
 #define BACKSPACE 263 /* ^G */
+#define C_C 4 /* ... */
+#define C_D 4 /* quit */
+#define        C_A 1 /* BOL */
+#define        C_B 2 /* BOL */
+#define C_E 5 /* EOL */
+#define        C_U 21 /* CLR TO BOL */
+#define        C_H 8  /* BACKSPACE */
+#define        C_W 23 /* DELETE PREVWORD */
+#define        C_L 12 /* Signal SIGWINCH */
+#define        C_R 18 /* hah not going to implement that */
+
+#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 (1 << 11)
+#define RECVMAX 17663 /* (1 << 11) */
 
 #define streq(a,b) (!strcmp(a,b))
 #define strneq(a,b,c) (!memcmp(a,b,c))
 int g_y, g_x;
 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 hardrefresh(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;
        signal(SIGWINCH, SIG_IGN);
@@ -51,17 +84,23 @@ void  init_screen(int x) {
        g_y = w.ws_row;
        g_x = w.ws_col;
        initscr();
-       cbreak();
+       raw();
        noecho();
        keypad(stdscr, ERR);
        nodelay(stdscr, TRUE);
+       ESCDELAY = 0;
        clear();
+       hardrefresh();
+       g_hardrefresh = 1;
 
        signal(SIGWINCH, init_screen);
 }
 
-void free_connection(void) {
-       close(g_sockfd);
+void stop(void) {
+       int sockfd = g_sockfd;
+       endwin();
+       printf("stopping now. maybe you forgot torify?\n");
+       if (sockfd > -1) { close(sockfd); }
        g_sockfd = -1;
 }
 
@@ -71,11 +110,11 @@ int init_connection(char * serv, char * port) {
        struct addrinfo hints, * res;
 
        memset(&hints, 0, sizeof(struct addrinfo));
-       hints.ai_family = AF_UNSPEC;     // don't care IPv4 or IPv6
-       hints.ai_socktype = SOCK_STREAM; // TCP stream sockets
+       hints.ai_family = AF_UNSPEC;    
+       hints.ai_socktype = SOCK_STREAM;
 
        if ((status = getaddrinfo(serv, port, &hints, &res)) != 0) {
-               fprintf(stderr, "init_connection: %s\n", gai_strerror(status));
+               perror("init_connection");
                exit(1);
        }
 
@@ -89,6 +128,7 @@ int init_connection(char * serv, char * port) {
        g_sockfd = sockfd;
        return sockfd;
 error:
+       if (sockfd > -1) { close(sockfd); }
        perror("init_connection");
        exit(1);
        __builtin_unreachable();
@@ -107,6 +147,15 @@ int countlines(char * buf, size_t len) {
        return i;
 }
 
+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;
+}
+
 size_t lastline(char * buf, size_t len) {
        size_t ret;
        char * start = buf;
@@ -151,39 +200,38 @@ int main (int argc, char ** argv) {
                        return 1;
                }
                if      (streq(*(argv-1), "-serv")) {
-                       printf("serv: %s\n", *argv);
                        serv = *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(void (*endwin)(void)); */
        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();
        clear();
 
+       atexit(stop);
        sockfd = init_connection(serv, port);
 
        char raw[SENDMAX + RECVMAX];
        char * sendbuf = raw, * recvbuf = raw + SENDMAX;
        size_t sendminlen;
-       size_t sendlen = sendminlen, recvlen = 0;
+       size_t sendlen = sendminlen, recvlen = 1;
 
        time_t t;
        struct tm * tm;
-       int frame = 15.;
-       float interval = 1. / frame;
+       useconds_t frame = 25;
+       useconds_t interval = 1000000 / frame;
        int32_t ct = 0;
+       int lc, off;
        int ch;
        int ret;
 
@@ -196,75 +244,60 @@ int main (int argc, char ** argv) {
        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
-
+       hardrefresh();
+       mvaddnstr(g_y - 1, 0, sendbuf, sendlen);
 
        while (1) {
                /* update */
-               if (ct % frame == 0) {
+               if (ct % (frame)  == 0) {
                        UPDATE_TIME();
+                       mvaddnstr(g_y - 1, 0, sendbuf, sendlen);
                }
                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);
+                       if (ret > 0 || g_hardrefresh) {
+                               recvlen += ret;
+                               lc = countlines(recvbuf, recvlen);
+                               off = lc - g_y - 4;
+                               off = getoff(recvbuf, recvlen, (off > 0) * off, '\n');
+                               mvaddnstr(1, 0, recvbuf + off, recvlen - off);
+                               g_hardrefresh = 0;
+                       }
                }
                /* send */
-               ch = getch();
-               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);
-               }
-               else if (ch == BACKSPACE) {
-                       clearline(g_y - 1);
-                       if (sendlen - 1 >= sendminlen)
-                       { --sendlen; }
+               while ((ch = getch()) != -1) {
+                       if (ch == '\n') {
+                               if (sendlen == sendminlen) { continue; }
+                               UPDATE_TIME();
+                               sendbuf[sendlen++] = '\n'; /* terminator */
+                               send(sockfd, sendbuf, sendlen, 0);
+                               memcpy(recvbuf + recvlen, sendbuf, (sendlen + recvlen < RECVMAX) * sendlen);
+                               recvlen += sendlen;
+                               mvaddnstr(1, 0, recvbuf, recvlen);
+                               mvaddch(g_y - 1, sendminlen, ' ');
+                               clearline(g_y - 1);
+                               sendlen = sendminlen;
+                       }
+                       else if (ch == C_D) {
+                               exit(0);
+                       }
+                       else if (ch == BACKSPACE) {
+                               clearline(g_y - 1);
+                               if (sendlen - 1 >= sendminlen)
+                               { mvaddch(g_y - 1, --sendlen, ' '); }
+                               mvaddnstr(g_y - 1, 0, sendbuf, sendlen);
+                               move(g_y - 1, sendlen);
+                       }
+                       else if (ch > 31 && ch < 127) {
+                               if (sendlen + 1 < SENDMAX)
+                               { sendbuf[sendlen++] = ch; }
+                               mvaddnstr(g_y - 1, 0, sendbuf, 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();
+               usleep(interval);
        }
+       return 0;
 }
diff --git a/server/blackhole/blackhole.c b/server/blackhole/blackhole.c
new file mode 100644 (file)
index 0000000..f2a3935
--- /dev/null
@@ -0,0 +1,119 @@
+/* blackhole.c - eats incoming messages, does nothing, just for testing
+ * @BAKE cc -O2 -std=gnu89 -Wall -Wextra -Wpedantic $@ -o $*
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <errno.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netdb.h>
+#include <arpa/inet.h>
+#include <sys/wait.h>
+#include <signal.h>
+
+#define PORT "91991"
+#define BACKLOG 1
+
+void sigchld_handler(int s) {
+       int saved_errno = errno;
+       (void)s;
+       while(waitpid(-1, NULL, WNOHANG) > 0);
+       errno = saved_errno;
+}
+
+void *get_in_addr(struct sockaddr *sa) {
+       if (sa->sa_family == AF_INET) {
+               return &(((struct sockaddr_in*)sa)->sin_addr);
+       }
+
+       return &(((struct sockaddr_in6*)sa)->sin6_addr);
+}
+
+int main (void) {
+       int sockfd, connfd, rv, yes = 1;
+       struct addrinfo hints, *servinfo, *p;
+       struct sockaddr_storage their_addr;
+       char s[INET6_ADDRSTRLEN];
+       socklen_t sin_size;
+       struct sigaction sa;
+
+       memset(&hints, 0, sizeof hints);
+       hints.ai_family = AF_UNSPEC;
+       hints.ai_socktype = SOCK_STREAM;
+       hints.ai_flags = AI_PASSIVE;
+
+       if ((rv = getaddrinfo(NULL, PORT, &hints, &servinfo)) != 0) {
+               fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(rv));
+               return 1;
+       }
+
+       for(p = servinfo; p != NULL; p = p->ai_next) {
+               if ((sockfd = socket(p->ai_family, p->ai_socktype,
+                                    p->ai_protocol)) == -1) {
+                       perror("server: socket");
+                       continue;
+               }
+               if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &yes,
+                              sizeof(int)) == -1) {
+                       perror("setsockopt");
+                       exit(1);
+               }
+               if (bind(sockfd, p->ai_addr, p->ai_addrlen) == -1) {
+                       close(sockfd);
+                       perror("server: bind");
+                       continue;
+               }
+               break;
+       }
+
+       freeaddrinfo(servinfo);
+
+       if (p == NULL)  {
+               fprintf(stderr, "server: failed to bind\n");
+               exit(1);
+       }
+
+       if (listen(sockfd, BACKLOG) == -1) {
+               perror("listen");
+               exit(1);
+       }
+
+       sa.sa_handler = sigchld_handler;
+       sigemptyset(&sa.sa_mask);
+       sa.sa_flags = SA_RESTART;
+       if (sigaction(SIGCHLD, &sa, NULL) == -1) {
+               perror("sigaction");
+               exit(1);
+       }
+
+       printf("server: waiting for connections...\n");
+
+       while (1) {
+               sin_size = sizeof their_addr;
+               connfd = accept(sockfd, (struct sockaddr *)&their_addr, &sin_size);
+
+               if (connfd == -1) {
+                       perror("accept");
+                       continue;
+               }
+
+               inet_ntop(their_addr.ss_family, get_in_addr((struct sockaddr *)&their_addr), s, sizeof s);
+
+               printf("server: got connection from %s\n", s);
+
+               if (!fork()) {
+                       close(sockfd);
+                       while (1) { sleep(5); }
+                       close(connfd);
+                       exit(0);
+               }
+               close(connfd);
+       }
+       close(sockfd);
+       sockfd = -1;
+       return 0;
+}