Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/srv/hid/remcons/remcons.c

    r9d5cea6 r4c6fd56  
    11/*
    2  * Copyright (c) 2024 Jiri Svoboda
     2 * Copyright (c) 2023 Jiri Svoboda
    33 * Copyright (c) 2012 Vojtech Horky
    44 * All rights reserved.
     
    3434 */
    3535
    36 #include <adt/list.h>
    37 #include <as.h>
    3836#include <async.h>
    3937#include <errno.h>
     
    5351#include <inttypes.h>
    5452#include <str.h>
    55 #include <vt/vt100.h>
    5653#include "telnet.h"
    5754#include "user.h"
    58 #include "remcons.h"
    5955
    6056#define APP_GETTERM  "/app/getterm"
    6157#define APP_SHELL "/app/bdsh"
    62 
    63 #define DEF_PORT 2223
    6458
    6559/** Telnet commands to force character mode
     
    8074static errno_t remcons_open(con_srvs_t *, con_srv_t *);
    8175static errno_t remcons_close(con_srv_t *);
    82 static errno_t remcons_read(con_srv_t *, void *, size_t, size_t *);
    8376static errno_t remcons_write(con_srv_t *, void *, size_t, size_t *);
    8477static void remcons_sync(con_srv_t *);
     
    8881static errno_t remcons_get_size(con_srv_t *, sysarg_t *, sysarg_t *);
    8982static errno_t remcons_get_color_cap(con_srv_t *, console_caps_t *);
    90 static void remcons_set_style(con_srv_t *, console_style_t);
    91 static void remcons_set_color(con_srv_t *, console_color_t,
    92     console_color_t, console_color_attr_t);
    93 static void remcons_set_color(con_srv_t *, console_color_t,
    94     console_color_t, console_color_attr_t);
    95 static void remcons_set_rgb_color(con_srv_t *, pixel_t, pixel_t);
    96 static void remcons_cursor_visibility(con_srv_t *, bool);
    97 static errno_t remcons_set_caption(con_srv_t *, const char *);
    9883static errno_t remcons_get_event(con_srv_t *, cons_event_t *);
    99 static errno_t remcons_map(con_srv_t *, sysarg_t, sysarg_t, charfield_t **);
    100 static void remcons_unmap(con_srv_t *);
    101 static void remcons_update(con_srv_t *, sysarg_t, sysarg_t, sysarg_t,
    102     sysarg_t);
    10384
    10485static con_ops_t con_ops = {
    10586        .open = remcons_open,
    10687        .close = remcons_close,
    107         .read = remcons_read,
     88        .read = NULL,
    10889        .write = remcons_write,
    10990        .sync = remcons_sync,
     
    11394        .get_size = remcons_get_size,
    11495        .get_color_cap = remcons_get_color_cap,
    115         .set_style = remcons_set_style,
    116         .set_color = remcons_set_color,
    117         .set_rgb_color = remcons_set_rgb_color,
    118         .set_cursor_visibility = remcons_cursor_visibility,
    119         .set_caption = remcons_set_caption,
    120         .get_event = remcons_get_event,
    121         .map = remcons_map,
    122         .unmap = remcons_unmap,
    123         .update = remcons_update
    124 };
    125 
    126 static void remcons_vt_putchar(void *, char32_t);
    127 static void remcons_vt_cputs(void *, const char *);
    128 static void remcons_vt_flush(void *);
    129 static void remcons_vt_key(void *, keymod_t, keycode_t, char);
    130 static void remcons_vt_pos_event(void *, pos_event_t *);
    131 
    132 static vt100_cb_t remcons_vt_cb = {
    133         .putuchar = remcons_vt_putchar,
    134         .control_puts = remcons_vt_cputs,
    135         .flush = remcons_vt_flush,
    136         .key = remcons_vt_key,
    137         .pos_event = remcons_vt_pos_event
     96        .set_style = NULL,
     97        .set_color = NULL,
     98        .set_rgb_color = NULL,
     99        .set_cursor_visibility = NULL,
     100        .get_event = remcons_get_event
    138101};
    139102
     
    148111};
    149112
    150 static void remcons_telnet_ws_update(void *, unsigned, unsigned);
    151 
    152 static telnet_cb_t remcons_telnet_cb = {
    153         .ws_update = remcons_telnet_ws_update
    154 };
    155 
    156113static loc_srv_t *remcons_srv;
    157 static bool no_ctl;
    158 static bool no_rgb;
    159114
    160115static telnet_user_t *srv_to_user(con_srv_t *srv)
    161116{
    162         remcons_t *remcons = (remcons_t *)srv->srvs->sarg;
    163         return remcons->user;
    164 }
    165 
    166 static remcons_t *srv_to_remcons(con_srv_t *srv)
    167 {
    168         remcons_t *remcons = (remcons_t *)srv->srvs->sarg;
    169         return remcons;
     117        return srv->srvs->sarg;
    170118}
    171119
     
    193141}
    194142
    195 static errno_t remcons_read(con_srv_t *srv, void *data, size_t size,
    196     size_t *nread)
     143static errno_t remcons_write(con_srv_t *srv, void *data, size_t size, size_t *nwritten)
    197144{
    198145        telnet_user_t *user = srv_to_user(srv);
    199146        errno_t rc;
    200147
    201         rc = telnet_user_recv(user, data, size, nread);
     148        rc = telnet_user_send_data(user, data, size);
    202149        if (rc != EOK)
    203150                return rc;
    204151
    205         return EOK;
    206 }
    207 
    208 static errno_t remcons_write(con_srv_t *srv, void *data, size_t size, size_t *nwritten)
    209 {
    210         remcons_t *remcons = srv_to_remcons(srv);
     152        *nwritten = size;
     153        return EOK;
     154}
     155
     156static void remcons_sync(con_srv_t *srv)
     157{
     158        (void) srv;
     159}
     160
     161static void remcons_clear(con_srv_t *srv)
     162{
     163        (void) srv;
     164}
     165
     166static void remcons_set_pos(con_srv_t *srv, sysarg_t col, sysarg_t row)
     167{
     168        telnet_user_t *user = srv_to_user(srv);
     169
     170        telnet_user_update_cursor_x(user, col);
     171}
     172
     173static errno_t remcons_get_pos(con_srv_t *srv, sysarg_t *col, sysarg_t *row)
     174{
     175        telnet_user_t *user = srv_to_user(srv);
     176
     177        *col = user->cursor_x;
     178        *row = 0;
     179
     180        return EOK;
     181}
     182
     183static errno_t remcons_get_size(con_srv_t *srv, sysarg_t *cols, sysarg_t *rows)
     184{
     185        (void) srv;
     186
     187        *cols = 100;
     188        *rows = 1;
     189
     190        return EOK;
     191}
     192
     193static errno_t remcons_get_color_cap(con_srv_t *srv, console_caps_t *ccaps)
     194{
     195        (void) srv;
     196        *ccaps = CONSOLE_CAP_NONE;
     197
     198        return EOK;
     199}
     200
     201static errno_t remcons_get_event(con_srv_t *srv, cons_event_t *event)
     202{
     203        telnet_user_t *user = srv_to_user(srv);
     204        kbd_event_t kevent;
    211205        errno_t rc;
    212206
    213         rc = telnet_user_send_data(remcons->user, data, size);
    214         if (rc != EOK)
    215                 return rc;
    216 
    217         rc = telnet_user_flush(remcons->user);
    218         if (rc != EOK)
    219                 return rc;
    220 
    221         *nwritten = size;
    222         return EOK;
    223 }
    224 
    225 static void remcons_sync(con_srv_t *srv)
    226 {
    227         (void) srv;
    228 }
    229 
    230 static void remcons_clear(con_srv_t *srv)
    231 {
    232         remcons_t *remcons = srv_to_remcons(srv);
    233 
    234         if (remcons->enable_ctl) {
    235                 vt100_cls(remcons->vt);
    236                 vt100_set_pos(remcons->vt, 0, 0);
    237                 remcons->user->cursor_x = 0;
    238                 remcons->user->cursor_y = 0;
    239         }
    240 }
    241 
    242 static void remcons_set_pos(con_srv_t *srv, sysarg_t col, sysarg_t row)
    243 {
    244         remcons_t *remcons = srv_to_remcons(srv);
    245         telnet_user_t *user = srv_to_user(srv);
    246 
    247         if (remcons->enable_ctl) {
    248                 vt100_set_pos(remcons->vt, col, row);
    249                 remcons->user->cursor_x = col;
    250                 remcons->user->cursor_y = row;
    251                 (void)telnet_user_flush(remcons->user);
    252         } else {
    253                 telnet_user_update_cursor_x(user, col);
    254         }
    255 }
    256 
    257 static errno_t remcons_get_pos(con_srv_t *srv, sysarg_t *col, sysarg_t *row)
    258 {
    259         telnet_user_t *user = srv_to_user(srv);
    260 
    261         *col = user->cursor_x;
    262         *row = user->cursor_y;
    263 
    264         return EOK;
    265 }
    266 
    267 static errno_t remcons_get_size(con_srv_t *srv, sysarg_t *cols, sysarg_t *rows)
    268 {
    269         remcons_t *remcons = srv_to_remcons(srv);
    270 
    271         if (remcons->enable_ctl) {
    272                 *cols = remcons->vt->cols;
    273                 *rows = remcons->vt->rows;
    274         } else {
    275                 *cols = 100;
    276                 *rows = 1;
    277         }
    278 
    279         return EOK;
    280 }
    281 
    282 static errno_t remcons_get_color_cap(con_srv_t *srv, console_caps_t *ccaps)
    283 {
    284         remcons_t *remcons = srv_to_remcons(srv);
    285 
    286         *ccaps = 0;
    287 
    288         if (remcons->enable_ctl) {
    289                 *ccaps |= CONSOLE_CAP_CURSORCTL | CONSOLE_CAP_STYLE |
    290                     CONSOLE_CAP_INDEXED;
    291         }
    292 
    293         if (remcons->enable_rgb)
    294                 *ccaps |= CONSOLE_CAP_RGB;
    295 
    296         return EOK;
    297 }
    298 
    299 static void remcons_set_style(con_srv_t *srv, console_style_t style)
    300 {
    301         remcons_t *remcons = srv_to_remcons(srv);
    302         char_attrs_t attrs;
    303 
    304         if (remcons->enable_ctl) {
    305                 attrs.type = CHAR_ATTR_STYLE;
    306                 attrs.val.style = style;
    307                 vt100_set_attr(remcons->vt, attrs);
    308         }
    309 }
    310 
    311 static void remcons_set_color(con_srv_t *srv, console_color_t bgcolor,
    312     console_color_t fgcolor, console_color_attr_t flags)
    313 {
    314         remcons_t *remcons = srv_to_remcons(srv);
    315         char_attrs_t attrs;
    316 
    317         if (remcons->enable_ctl) {
    318                 attrs.type = CHAR_ATTR_INDEX;
    319                 attrs.val.index.bgcolor = bgcolor;
    320                 attrs.val.index.fgcolor = fgcolor;
    321                 attrs.val.index.attr = flags;
    322                 vt100_set_attr(remcons->vt, attrs);
    323         }
    324 }
    325 
    326 static void remcons_set_rgb_color(con_srv_t *srv, pixel_t bgcolor,
    327     pixel_t fgcolor)
    328 {
    329         remcons_t *remcons = srv_to_remcons(srv);
    330         char_attrs_t attrs;
    331 
    332         if (remcons->enable_ctl) {
    333                 attrs.type = CHAR_ATTR_RGB;
    334                 attrs.val.rgb.bgcolor = bgcolor;
    335                 attrs.val.rgb.fgcolor = fgcolor;
    336                 vt100_set_attr(remcons->vt, attrs);
    337         }
    338 }
    339 
    340 static void remcons_cursor_visibility(con_srv_t *srv, bool visible)
    341 {
    342         remcons_t *remcons = srv_to_remcons(srv);
    343 
    344         if (remcons->enable_ctl) {
    345                 if (!remcons->curs_visible && visible) {
    346                         vt100_set_pos(remcons->vt, remcons->user->cursor_x,
    347                             remcons->user->cursor_y);
    348                 }
    349                 vt100_cursor_visibility(remcons->vt, visible);
    350         }
    351 
    352         remcons->curs_visible = visible;
    353 }
    354 
    355 static errno_t remcons_set_caption(con_srv_t *srv, const char *caption)
    356 {
    357         remcons_t *remcons = srv_to_remcons(srv);
    358 
    359         if (remcons->enable_ctl) {
    360                 vt100_set_title(remcons->vt, caption);
    361         }
    362 
    363         return EOK;
    364 }
    365 
    366 /** Creates new keyboard event from given char.
    367  *
    368  * @param type Event type (press / release).
    369  * @param c Pressed character.
    370  */
    371 static remcons_event_t *new_kbd_event(kbd_event_type_t type, keymod_t mods,
    372     keycode_t key, char c)
    373 {
    374         remcons_event_t *event = malloc(sizeof(remcons_event_t));
    375         if (event == NULL) {
    376                 fprintf(stderr, "Out of memory.\n");
    377                 return NULL;
    378         }
    379 
    380         link_initialize(&event->link);
    381         event->cev.type = CEV_KEY;
    382         event->cev.ev.key.type = type;
    383         event->cev.ev.key.mods = mods;
    384         event->cev.ev.key.key = key;
    385         event->cev.ev.key.c = c;
    386 
    387         return event;
    388 }
    389 
    390 /** Creates new position event.
    391  *
    392  * @param ev Position event.
    393  * @param c Pressed character.
    394  */
    395 static remcons_event_t *new_pos_event(pos_event_t *ev)
    396 {
    397         remcons_event_t *event = malloc(sizeof(remcons_event_t));
    398         if (event == NULL) {
    399                 fprintf(stderr, "Out of memory.\n");
    400                 return NULL;
    401         }
    402 
    403         link_initialize(&event->link);
    404         event->cev.type = CEV_POS;
    405         event->cev.ev.pos = *ev;
    406 
    407         return event;
    408 }
    409 
    410 /** Creates new console resize event.
    411  */
    412 static remcons_event_t *new_resize_event(void)
    413 {
    414         remcons_event_t *event = malloc(sizeof(remcons_event_t));
    415         if (event == NULL) {
    416                 fprintf(stderr, "Out of memory.\n");
    417                 return NULL;
    418         }
    419 
    420         link_initialize(&event->link);
    421         event->cev.type = CEV_RESIZE;
    422 
    423         return event;
    424 }
    425 
    426 static errno_t remcons_get_event(con_srv_t *srv, cons_event_t *event)
    427 {
    428         remcons_t *remcons = srv_to_remcons(srv);
    429         telnet_user_t *user = srv_to_user(srv);
    430         size_t nread;
    431 
    432         while (list_empty(&remcons->in_events)) {
    433                 char next_byte = 0;
    434 
    435                 errno_t rc = telnet_user_recv(user, &next_byte, 1,
    436                     &nread);
    437                 if (rc != EOK)
    438                         return rc;
    439 
    440                 vt100_rcvd_char(remcons->vt, next_byte);
    441         }
    442 
    443         link_t *link = list_first(&remcons->in_events);
    444         list_remove(link);
    445 
    446         remcons_event_t *tmp = list_get_instance(link, remcons_event_t, link);
    447 
    448         *event = tmp->cev;
    449         free(tmp);
    450 
    451         return EOK;
    452 }
    453 
    454 static errno_t remcons_map(con_srv_t *srv, sysarg_t cols, sysarg_t rows,
    455     charfield_t **rbuf)
    456 {
    457         remcons_t *remcons = srv_to_remcons(srv);
    458         void *buf;
    459 
    460         if (!remcons->enable_ctl)
    461                 return ENOTSUP;
    462 
    463         if (remcons->ubuf != NULL)
    464                 return EBUSY;
    465 
    466         buf = as_area_create(AS_AREA_ANY, cols * rows * sizeof(charfield_t),
    467             AS_AREA_READ | AS_AREA_WRITE | AS_AREA_CACHEABLE, AS_AREA_UNPAGED);
    468         if (buf == AS_MAP_FAILED)
    469                 return ENOMEM;
    470 
    471         remcons->ucols = cols;
    472         remcons->urows = rows;
    473         remcons->ubuf = buf;
    474 
    475         *rbuf = buf;
    476         return EOK;
    477 
    478 }
    479 
    480 static void remcons_unmap(con_srv_t *srv)
    481 {
    482         remcons_t *remcons = srv_to_remcons(srv);
    483         void *buf;
    484 
    485         buf = remcons->ubuf;
    486         remcons->ubuf = NULL;
    487 
    488         if (buf != NULL)
    489                 as_area_destroy(buf);
    490 }
    491 
    492 static void remcons_update(con_srv_t *srv, sysarg_t c0, sysarg_t r0,
    493     sysarg_t c1, sysarg_t r1)
    494 {
    495         remcons_t *remcons = srv_to_remcons(srv);
    496         charfield_t *ch;
    497         sysarg_t col, row;
    498         sysarg_t old_x, old_y;
    499 
    500         if (remcons->ubuf == NULL)
    501                 return;
    502 
    503         /* Make sure we have meaningful coordinates, within bounds */
    504 
    505         if (c1 > remcons->ucols)
    506                 c1 = remcons->ucols;
    507         if (c1 > remcons->user->cols)
    508                 c1 = remcons->user->cols;
    509         if (c0 >= c1)
    510                 return;
    511 
    512         if (r1 > remcons->urows)
    513                 r1 = remcons->urows;
    514         if (r1 > remcons->user->rows)
    515                 r1 = remcons->user->rows;
    516         if (r0 >= r1)
    517                 return;
    518 
    519         /* Update screen from user buffer */
    520 
    521         old_x = remcons->user->cursor_x;
    522         old_y = remcons->user->cursor_y;
    523 
    524         if (remcons->curs_visible)
    525                 vt100_cursor_visibility(remcons->vt, false);
    526 
    527         for (row = r0; row < r1; row++) {
    528                 for (col = c0; col < c1; col++) {
    529                         vt100_set_pos(remcons->vt, col, row);
    530                         ch = &remcons->ubuf[row * remcons->ucols + col];
    531                         vt100_set_attr(remcons->vt, ch->attrs);
    532                         vt100_putuchar(remcons->vt, ch->ch);
    533                 }
    534         }
    535 
    536         if (remcons->curs_visible) {
    537                 old_x = remcons->user->cursor_x = old_x;
    538                 remcons->user->cursor_y = old_y;
    539                 vt100_set_pos(remcons->vt, old_x, old_y);
    540                 vt100_cursor_visibility(remcons->vt, true);
    541         }
    542 
    543         /* Flush data */
    544         (void)telnet_user_flush(remcons->user);
     207        rc = telnet_user_get_next_keyboard_event(user, &kevent);
     208        if (rc != EOK) {
     209                /* XXX What? */
     210                memset(event, 0, sizeof(*event));
     211                return EOK;
     212        }
     213
     214        event->type = CEV_KEY;
     215        event->ev.key = kevent;
     216
     217        return EOK;
    545218}
    546219
     
    575248                    "failed: %s.", APP_GETTERM, user->service_name, APP_SHELL,
    576249                    str_error(rc));
    577                 fibril_mutex_lock(&user->recv_lock);
     250                fibril_mutex_lock(&user->guard);
    578251                user->task_finished = true;
    579252                user->srvs.aborted = true;
    580253                fibril_condvar_signal(&user->refcount_cv);
    581                 fibril_mutex_unlock(&user->recv_lock);
     254                fibril_mutex_unlock(&user->guard);
    582255                return EOK;
    583256        }
    584257
    585         fibril_mutex_lock(&user->recv_lock);
     258        fibril_mutex_lock(&user->guard);
    586259        user->task_id = task;
    587         fibril_mutex_unlock(&user->recv_lock);
     260        fibril_mutex_unlock(&user->guard);
    588261
    589262        task_exit_t task_exit;
     
    595268
    596269        /* Announce destruction. */
    597         fibril_mutex_lock(&user->recv_lock);
     270        fibril_mutex_lock(&user->guard);
    598271        user->task_finished = true;
    599272        user->srvs.aborted = true;
    600273        fibril_condvar_signal(&user->refcount_cv);
    601         fibril_mutex_unlock(&user->recv_lock);
     274        fibril_mutex_unlock(&user->guard);
    602275
    603276        return EOK;
     
    614287}
    615288
    616 static void remcons_vt_putchar(void *arg, char32_t c)
    617 {
    618         remcons_t *remcons = (remcons_t *)arg;
    619         char buf[STR_BOUNDS(1)];
    620         size_t off;
    621         errno_t rc;
    622 
    623         (void)arg;
    624 
    625         off = 0;
    626         rc = chr_encode(c, buf, &off, sizeof(buf));
    627         if (rc != EOK)
    628                 return;
    629 
    630         (void)telnet_user_send_data(remcons->user, buf, off);
    631 }
    632 
    633 static void remcons_vt_cputs(void *arg, const char *str)
    634 {
    635         remcons_t *remcons = (remcons_t *)arg;
    636 
    637         (void)telnet_user_send_raw(remcons->user, str, str_size(str));
    638 }
    639 
    640 static void remcons_vt_flush(void *arg)
    641 {
    642         remcons_t *remcons = (remcons_t *)arg;
    643         (void)telnet_user_flush(remcons->user);
    644 }
    645 
    646 static void remcons_vt_key(void *arg, keymod_t mods, keycode_t key, char c)
    647 {
    648         remcons_t *remcons = (remcons_t *)arg;
    649 
    650         remcons_event_t *down = new_kbd_event(KEY_PRESS, mods, key, c);
    651         if (down == NULL)
    652                 return;
    653 
    654         remcons_event_t *up = new_kbd_event(KEY_RELEASE, mods, key, c);
    655         if (up == NULL) {
    656                 free(down);
    657                 return;
    658         }
    659 
    660         list_append(&down->link, &remcons->in_events);
    661         list_append(&up->link, &remcons->in_events);
    662 }
    663 
    664 static void remcons_vt_pos_event(void *arg, pos_event_t *ev)
    665 {
    666         remcons_t *remcons = (remcons_t *)arg;
    667 
    668         remcons_event_t *cev = new_pos_event(ev);
    669         if (cev == NULL)
    670                 return;
    671 
    672         list_append(&cev->link, &remcons->in_events);
    673 }
    674 
    675 /** Window size update callback.
    676  *
    677  * @param arg Argument (remcons_t *)
    678  * @param cols New number of columns
    679  * @param rows New number of rows
    680  */
    681 static void remcons_telnet_ws_update(void *arg, unsigned cols, unsigned rows)
    682 {
    683         remcons_t *remcons = (remcons_t *)arg;
    684 
    685         vt100_resize(remcons->vt, cols, rows);
    686         telnet_user_resize(remcons->user, cols, rows);
    687 
    688         remcons_event_t *resize = new_resize_event();
    689         if (resize == NULL)
    690                 return;
    691 
    692         list_append(&resize->link, &remcons->in_events);
    693 }
    694 
    695289/** Handle network connection.
    696290 *
     
    700294static void remcons_new_conn(tcp_listener_t *lst, tcp_conn_t *conn)
    701295{
    702         char_attrs_t attrs;
    703         remcons_t *remcons = NULL;
    704         telnet_user_t *user = NULL;
    705 
    706         remcons = calloc(1, sizeof(remcons_t));
    707         if (remcons == NULL) {
    708                 fprintf(stderr, "Out of memory.\n");
    709                 goto error;
    710         }
    711 
    712         user = telnet_user_create(conn, &remcons_telnet_cb,
    713             (void *)remcons);
    714         if (user == NULL) {
    715                 fprintf(stderr, "Out of memory.\n");
    716                 goto error;
    717         }
    718 
    719         remcons->enable_ctl = !no_ctl;
    720         remcons->enable_rgb = !no_ctl && !no_rgb;
    721         remcons->user = user;
    722         list_initialize(&remcons->in_events);
    723 
    724         if (remcons->enable_ctl) {
    725                 user->cols = 80;
    726                 user->rows = 25;
    727         } else {
    728                 user->cols = 100;
    729                 user->rows = 1;
    730         }
    731 
    732         remcons->curs_visible = true;
    733 
    734         remcons->vt = vt100_create((void *)remcons, 80, 25, &remcons_vt_cb);
    735         if (remcons->vt == NULL) {
    736                 fprintf(stderr, "Error creating VT100 driver instance.\n");
    737                 goto error;
    738         }
    739 
    740         remcons->vt->enable_rgb = remcons->enable_rgb;
    741 
    742         if (remcons->enable_ctl) {
    743                 attrs.type = CHAR_ATTR_STYLE;
    744                 attrs.val.style = STYLE_NORMAL;
    745                 vt100_set_sgr(remcons->vt, attrs);
    746                 vt100_cls(remcons->vt);
    747                 vt100_set_pos(remcons->vt, 0, 0);
    748                 vt100_set_button_reporting(remcons->vt, true);
    749         }
     296        telnet_user_t *user = telnet_user_create(conn);
     297        assert(user);
    750298
    751299        con_srvs_init(&user->srvs);
    752300        user->srvs.ops = &con_ops;
    753         user->srvs.sarg = remcons;
    754         user->srvs.abort_timeout = 1000000;
     301        user->srvs.sarg = user;
     302        user->srvs.abort_timeout = 1000;
    755303
    756304        telnet_user_add(user);
     
    761309                telnet_user_error(user, "Unable to register %s with loc: %s.",
    762310                    user->service_name, str_error(rc));
    763                 goto error;
     311                return;
    764312        }
    765313
     
    768316
    769317        fid_t spawn_fibril = fibril_create(spawn_task_fibril, user);
    770         if (spawn_fibril == 0) {
    771                 fprintf(stderr, "Failed creating fibril.\n");
    772                 goto error;
    773         }
     318        assert(spawn_fibril);
    774319        fibril_add_ready(spawn_fibril);
    775320
    776321        /* Wait for all clients to exit. */
    777         fibril_mutex_lock(&user->recv_lock);
     322        fibril_mutex_lock(&user->guard);
    778323        while (!user_can_be_destroyed_no_lock(user)) {
    779324                if (user->task_finished) {
     325                        user->conn = NULL;
    780326                        user->socket_closed = true;
    781327                        user->srvs.aborted = true;
     328                        continue;
    782329                } else if (user->socket_closed) {
    783330                        if (user->task_id != 0) {
     
    785332                        }
    786333                }
    787                 fibril_condvar_wait_timeout(&user->refcount_cv,
    788                     &user->recv_lock, 1000000);
    789         }
    790         fibril_mutex_unlock(&user->recv_lock);
     334                fibril_condvar_wait_timeout(&user->refcount_cv, &user->guard, 1000);
     335        }
     336        fibril_mutex_unlock(&user->guard);
    791337
    792338        rc = loc_service_unregister(remcons_srv, user->service_id);
     
    798344
    799345        telnet_user_log(user, "Destroying...");
    800 
    801         if (remcons->enable_ctl) {
    802                 /* Disable mouse tracking */
    803                 vt100_set_button_reporting(remcons->vt, false);
    804 
    805                 /* Reset all character attributes and clear screen */
    806                 vt100_sgr(remcons->vt, 0);
    807                 vt100_cls(remcons->vt);
    808                 vt100_set_pos(remcons->vt, 0, 0);
    809 
    810                 telnet_user_flush(user);
    811         }
    812 
    813         tcp_conn_send_fin(user->conn);
    814         user->conn = NULL;
    815 
    816346        telnet_user_destroy(user);
    817         vt100_destroy(remcons->vt);
    818         free(remcons);
    819         return;
    820 error:
    821         if (user != NULL && user->service_id != 0)
    822                 loc_service_unregister(remcons_srv, user->service_id);
    823         if (user != NULL)
    824                 free(user);
    825         if (remcons != NULL && remcons->vt != NULL)
    826                 vt100_destroy(remcons->vt);
    827         if (remcons != NULL)
    828                 free(remcons);
    829 }
    830 
    831 static void print_syntax(void)
    832 {
    833         fprintf(stderr, "syntax: remcons [<options>]\n");
    834         fprintf(stderr, "\t--no-ctl      Disable all terminal control sequences\n");
    835         fprintf(stderr, "\t--no-rgb      Disable RGB colors\n");
    836         fprintf(stderr, "\t--port <port> Listening port (default: %u)\n",
    837             DEF_PORT);
    838347}
    839348
     
    844353        tcp_t *tcp;
    845354        inet_ep_t ep;
    846         uint16_t port;
    847         int i;
    848 
    849         port = DEF_PORT;
    850 
    851         i = 1;
    852         while (i < argc) {
    853                 if (argv[i][0] == '-') {
    854                         if (str_cmp(argv[i], "--no-ctl") == 0) {
    855                                 no_ctl = true;
    856                         } else if (str_cmp(argv[i], "--no-rgb") == 0) {
    857                                 no_rgb = true;
    858                         } else if (str_cmp(argv[i], "--port") == 0) {
    859                                 ++i;
    860                                 if (i >= argc) {
    861                                         fprintf(stderr, "Option argument "
    862                                             "missing.\n");
    863                                         print_syntax();
    864                                         return EINVAL;
    865                                 }
    866                                 rc = str_uint16_t(argv[i], NULL, 10, true, &port);
    867                                 if (rc != EOK) {
    868                                         fprintf(stderr, "Invalid port number "
    869                                             "'%s'.\n", argv[i]);
    870                                         print_syntax();
    871                                         return EINVAL;
    872                                 }
    873                         } else {
    874                                 fprintf(stderr, "Unknown option '%s'.\n",
    875                                     argv[i]);
    876                                 print_syntax();
    877                                 return EINVAL;
    878                         }
    879                 } else {
    880                         fprintf(stderr, "Unexpected argument.\n");
    881                         print_syntax();
    882                         return EINVAL;
    883                 }
    884 
    885                 ++i;
    886         }
    887355
    888356        async_set_fallback_port_handler(client_connection, NULL);
     
    900368
    901369        inet_ep_init(&ep);
    902         ep.port = port;
     370        ep.port = 2223;
    903371
    904372        rc = tcp_listener_create(tcp, &ep, &listen_cb, NULL, &conn_cb, NULL,
Note: See TracChangeset for help on using the changeset viewer.