jcs
/subtext
/amendments
/42
session: Add session_flush, make output routines not autoflush
This lets us flush at certain places to send it out once we've built
up a whole line or whatever to smooth out the output
jcs made amendment 42 over 2 years ago
--- session.c Wed Dec 29 20:50:48 2021
+++ session.c Sun Jan 2 10:22:55 2022
@@ -91,7 +91,8 @@ session_run(struct uthread *uthread, void *arg)
"Welcome to %s (%s)\r\n"
"\r\n", db->config.name, s->node);
}
-
+ session_flush(s);
+
if (session_login(s) != AUTH_USER_OK) {
session_close(&s);
return;
@@ -117,6 +118,7 @@ session_run(struct uthread *uthread, void *arg)
s->user ? s->user->username : GUEST_USERNAME,
ansi(s, ANSI_RESET, ANSI_END),
sessions_tally, ordinal(sessions_tally));
+ session_flush(s);
len = session_load_view(s, DB_TEXT_MENU_ID, &view);
if (len) {
@@ -124,9 +126,11 @@ session_run(struct uthread *uthread, void *arg)
free(view);
} else
session_output_string(s, "\r\n[ Menu missing! ]\r\n\r\n");
+ session_flush(s);
while (!done && !s->ending) {
session_output_string(s, "Main Menu> ");
+ session_flush(s);
get_another_char:
c = session_input_char(s);
@@ -136,6 +140,7 @@ get_another_char:
goto get_another_char;
session_printf(s, "%c\r\n", c);
+ session_flush(s);
/* TODO: make letter->command dynamic from a resource */
switch (c) {
@@ -147,6 +152,7 @@ get_another_char:
case 'G':
/* goodbye */
session_output_string(s, "Goodbye!\r\n");
+ session_flush(s);
done = 1;
break;
case 'w':
@@ -155,10 +161,11 @@ get_another_char:
break;
default:
session_output_string(s, "Invalid option\r\n");
+ session_flush(s);
break;
}
}
-
+
session_close(&s);
}
@@ -176,7 +183,7 @@ session_close(struct session **session)
(*session)->node_funcs->output(*session);
uthread_yield();
}
-
+
(*session)->ending = 1;
}
@@ -218,6 +225,23 @@ session_printf(struct session *session, const char *fo
return session_output(session, session_tbuf, len);
}
+void
+session_flush(struct session *session)
+{
+ if (session->ending)
+ return;
+ if (session->obuflen == 0)
+ return;
+
+ while (session->obuflen != 0) {
+ session->node_funcs->output(session);
+ if (session->obuflen != 0)
+ uthread_yield();
+ if (session->ending)
+ return;
+ }
+}
+
size_t
session_output(struct session *session, const char *str, size_t len)
{
@@ -226,8 +250,7 @@ session_output(struct session *session, const char *st
while (len && !session->ending) {
chunk = (sizeof(session->obuf) - session->obuflen);
if (chunk == 0) {
- /* wait until output buffer clears */
- uthread_yield();
+ session_flush(session);
if (session->ending)
return 0;
continue;
@@ -239,10 +262,6 @@ session_output(struct session *session, const char *st
session->obuflen += chunk;
stroff += chunk;
len -= chunk;
- session->node_funcs->output(session);
-
- if (len)
- uthread_yield();
}
return olen;
@@ -263,13 +282,15 @@ session_input_char(struct session *session)
wait_for_char:
while (session->ibuflen == 0) {
session->node_funcs->input(session);
- uthread_yield();
if (session->ending)
return 0;
+ if (session->abort_input)
+ return 0;
if (session->ibuflen != 0)
break;
if (session->obuflen != 0)
return 0;
+ uthread_yield();
}
ret = session->ibuf[0];
@@ -303,11 +324,13 @@ session_field_input(struct session *session, unsigned
char *field;
unsigned char c, redraw = 0;
+ session->abort_input = 0;
+
field = xmalloczero(size);
for (;;) {
c = session_input_char(session);
- if (session->ending)
+ if (session->ending || session->abort_input)
goto field_input_bail;
switch (c) {
case 0: /* session_input_char bailed */
@@ -336,9 +359,11 @@ session_field_input(struct session *session, unsigned
if (redraw) {
/* TODO */
- } else
+ } else {
session_output_string(session,
ansi(session, ANSI_BACKSPACE, ANSI_END));
+ session_flush(session);
+ }
break;
case '\r':
@@ -358,6 +383,7 @@ session_field_input(struct session *session, unsigned
ilen++;
field[ipos] = '\0';
session_output(session, mask ? &mask : (char *)&c, 1);
+ session_flush(session);
}
}
@@ -380,12 +406,15 @@ session_login(struct session *s)
if (s->autologin_username[0]) {
session_printf(s, "%s\r\n", s->autologin_username);
+ session_flush(s);
username = xstrdup(s->autologin_username);
} else {
+ session_flush(s);
username = session_field_input(s, DB_USERNAME_SIZE,
DB_USERNAME_SIZE - 1, 0);
session_output(s, "\r\n", 2);
-
+ session_flush(s);
+
if (username == NULL || s->ending)
goto login_bail;
@@ -415,8 +444,10 @@ session_login(struct session *s)
}
session_output_string(s, "Password: ");
+ session_flush(s);
password = session_field_input(s, 64, 64, '*');
session_output(s, "\r\n", 2);
+ session_flush(s);
if (password == NULL || s->ending)
goto login_bail;
@@ -443,6 +474,7 @@ session_login(struct session *s)
uthread_msleep(60);
session_output_string(s, "Login incorrect\r\n");
+ session_flush(s);
}
login_bail:
@@ -451,6 +483,7 @@ login_bail:
if (password)
free(password);
session_output_string(s, "Thanks for playing\r\n");
+ session_flush(s);
return AUTH_USER_FAILED;
}
@@ -634,6 +667,7 @@ session_pause_return(struct session *s, short enforce,
session_output_string(s, msg);
else
session_output_string(s, "to return to the main menu...");
+ session_flush(s);
for (;;) {
c = session_input_char(s);
@@ -643,6 +677,7 @@ session_pause_return(struct session *s, short enforce,
break;
}
session_output(s, "\r\n", 2);
+ session_flush(s);
}
void
@@ -659,6 +694,7 @@ session_who(struct session *s)
session_printf(s,
"%sNode User Via Speed Idle%s\r\n",
ansi(s, ANSI_BOLD, ANSI_END), ansi(s, ANSI_RESET, ANSI_END));
+ session_flush(s);
for (n = 0; n < nsessions; n++) {
idle = Time - sessions[n]->last_input_at;
@@ -677,8 +713,10 @@ session_who(struct session *s)
sessions[n]->via,
sessions[n]->tspeed,
idle_s);
+ session_flush(s);
}
session_output(s, "\r\n", 2);
+ session_flush(s);
session_pause_return(s, 0, NULL);
}
--- session.h Wed Dec 29 08:56:08 2021
+++ session.h Sun Jan 2 10:21:53 2022
@@ -48,16 +48,18 @@ struct session_log {
unsigned long ip_address;
};
+
struct session {
short ending;
char node[10];
char via[10];
- unsigned char obuf[256]; /* telnet.obuf must be double this */
+ unsigned char obuf[512]; /* telnet.obuf must be double this */
unsigned char ibuf[64];
short obuflen;
short ibuflen;
enum session_input_state input_state;
unsigned char last_input;
+ unsigned char abort_input;
unsigned long last_input_at;
unsigned short terminal_columns;
unsigned short terminal_lines;
@@ -86,6 +88,7 @@ struct session *session_create(char *node, char *via,
void session_close(struct session **session);
void session_idle(struct session *session);
char session_input_char(struct session *session);
+void session_flush(struct session *session);
size_t session_printf(struct session *session, const char *format, ...);
size_t session_output(struct session *session, const char *str, size_t len);
size_t session_output_string(struct session *session, const char *str);