Ignore:
File:
1 edited

Legend:

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

    r03e0a244 r902f0906  
    3434
    3535#include <async.h>
     36#include <errno.h>
     37#include <io/con_srv.h>
    3638#include <stdio.h>
    37 #include <adt/prodcons.h>
    38 #include <ipc/input.h>
    39 #include <ipc/console.h>
    40 #include <ipc/vfs.h>
    41 #include <errno.h>
     39#include <stdlib.h>
    4240#include <str_error.h>
    4341#include <loc.h>
     
    4543#include <io/keycode.h>
    4644#include <align.h>
    47 #include <malloc.h>
    48 #include <as.h>
    4945#include <fibril_synch.h>
    5046#include <task.h>
     
    7167        TELNET_IAC, TELNET_WONT, TELNET_LINEMODE
    7268};
     69
    7370static const size_t telnet_force_character_mode_command_count =
    7471    sizeof(telnet_force_character_mode_command) / sizeof(telnet_cmd_t);
    7572
    76 
    77 /** Handling client requests (VFS and console interface).
    78  *
    79  * @param user Telnet user the requests belong to.
    80  */
    81 static void client_connection_message_loop(telnet_user_t *user)
    82 {
    83         while (true) {
    84                 ipc_call_t call;
    85                 ipc_callid_t callid = 0;
    86 
    87                 /*
    88                  * The getterm task might terminate while we are here,
    89                  * waiting for a call. Also, the socket might be closed
    90                  * meanwhile.
    91                  * We want to detect this situation early, so we use a
    92                  * timeout variant of async_get_call().
    93                  */
    94                 while (callid == 0) {
    95                         callid = async_get_call_timeout(&call, 1000);
    96 
    97                         if (telnet_user_is_zombie(user)) {
    98                                 if (callid != 0) {
    99                                         async_answer_0(callid, EINTR);
    100                                 }
    101                                 return;
    102                         }
    103                 }
    104                
    105                 if (!IPC_GET_IMETHOD(call)) {
    106                         return;
    107                 }
    108 
    109                 switch (IPC_GET_IMETHOD(call)) {
    110                 case CONSOLE_GET_SIZE:
    111                         async_answer_2(callid, EOK, 100, 1);
    112                         break;
    113                 case CONSOLE_GET_POS:
    114                         fibril_mutex_lock(&user->guard);
    115                         async_answer_2(callid, EOK, user->cursor_x, 0);
    116                         fibril_mutex_unlock(&user->guard);
    117                         break;
    118                 case CONSOLE_GET_EVENT: {
    119                         kbd_event_t event;
    120                         int rc = telnet_user_get_next_keyboard_event(user, &event);
    121                         if (rc != EOK) {
    122                                 /* Silently ignore. */
    123                                 async_answer_0(callid, EOK);
    124                                 break;
    125                         }
    126                         async_answer_4(callid, EOK, event.type, event.key, event.mods, event.c);
    127                         break;
    128                 }
    129                 case CONSOLE_GOTO: {
    130                         int new_x = IPC_GET_ARG1(call);
    131                         telnet_user_update_cursor_x(user, new_x);
    132                         async_answer_0(callid, ENOTSUP);
    133                         break;
    134                 }
    135                 case VFS_OUT_READ:
    136                         async_answer_0(callid, ENOTSUP);
    137                         break;
    138                 case VFS_OUT_WRITE: {
    139                         uint8_t *buf;
    140                         size_t size;
    141                         int rc = async_data_write_accept((void **)&buf, false, 0, 0, 0, &size);
    142 
    143                         if (rc != EOK) {
    144                                 async_answer_0(callid, rc);
    145                                 break;
    146                         }
    147 
    148                         rc = telnet_user_send_data(user, buf, size);
    149                         free(buf);
    150 
    151                         if (rc != EOK) {
    152                                 async_answer_0(callid, rc);
    153                                 break;
    154                         }
    155 
    156                         async_answer_1(callid, EOK, size);
    157                         break;
    158                 }
    159                 case VFS_OUT_SYNC:
    160                         async_answer_0(callid, EOK);
    161                         break;
    162                 case CONSOLE_CLEAR:
    163                         async_answer_0(callid, EOK);
    164                         break;
    165 
    166                 case CONSOLE_GET_COLOR_CAP:
    167                         async_answer_1(callid, EOK, CONSOLE_CAP_NONE);
    168                         break;
    169                 case CONSOLE_SET_STYLE:
    170                         async_answer_0(callid, ENOTSUP);
    171                         break;
    172                 case CONSOLE_SET_COLOR:
    173                         async_answer_0(callid, ENOTSUP);
    174                         break;
    175                 case CONSOLE_SET_RGB_COLOR:
    176                         async_answer_0(callid, ENOTSUP);
    177                         break;
    178 
    179                 case CONSOLE_CURSOR_VISIBILITY:
    180                         async_answer_0(callid, ENOTSUP);
    181                         break;
    182 
    183                 default:
    184                         async_answer_0(callid, EINVAL);
    185                         break;
    186                 }
    187         }
     73static int remcons_open(con_srvs_t *, con_srv_t *);
     74static int remcons_close(con_srv_t *);
     75static int remcons_write(con_srv_t *, void *, size_t);
     76static void remcons_sync(con_srv_t *);
     77static void remcons_clear(con_srv_t *);
     78static void remcons_set_pos(con_srv_t *, sysarg_t col, sysarg_t row);
     79static int remcons_get_pos(con_srv_t *, sysarg_t *, sysarg_t *);
     80static int remcons_get_size(con_srv_t *, sysarg_t *, sysarg_t *);
     81static int remcons_get_color_cap(con_srv_t *, console_caps_t *);
     82static int remcons_get_event(con_srv_t *, cons_event_t *);
     83
     84static con_ops_t con_ops = {
     85        .open = remcons_open,
     86        .close = remcons_close,
     87        .read = NULL,
     88        .write = remcons_write,
     89        .sync = remcons_sync,
     90        .clear = remcons_clear,
     91        .set_pos = remcons_set_pos,
     92        .get_pos = remcons_get_pos,
     93        .get_size = remcons_get_size,
     94        .get_color_cap = remcons_get_color_cap,
     95        .set_style = NULL,
     96        .set_color = NULL,
     97        .set_rgb_color = NULL,
     98        .set_cursor_visibility = NULL,
     99        .get_event = remcons_get_event
     100};
     101
     102static telnet_user_t *srv_to_user(con_srv_t *srv)
     103{
     104        return srv->srvs->sarg;
     105}
     106
     107static int remcons_open(con_srvs_t *srvs, con_srv_t *srv)
     108{
     109        telnet_user_t *user = srv_to_user(srv);
     110
     111        telnet_user_log(user, "New client connected (%p).", srv);
     112
     113        /* Force character mode. */
     114        send(user->socket, (void *)telnet_force_character_mode_command,
     115            telnet_force_character_mode_command_count, 0);
     116
     117        return EOK;
     118}
     119
     120static int remcons_close(con_srv_t *srv)
     121{
     122        telnet_user_t *user = srv_to_user(srv);
     123
     124        telnet_user_notify_client_disconnected(user);
     125        telnet_user_log(user, "Client disconnected (%p).", srv);
     126
     127        return EOK;
     128}
     129
     130static int remcons_write(con_srv_t *srv, void *data, size_t size)
     131{
     132        telnet_user_t *user = srv_to_user(srv);
     133        int rc;
     134
     135        rc = telnet_user_send_data(user, data, size);
     136        if (rc != EOK)
     137                return rc;
     138
     139        return size;
     140}
     141
     142static void remcons_sync(con_srv_t *srv)
     143{
     144        (void) srv;
     145}
     146
     147static void remcons_clear(con_srv_t *srv)
     148{
     149        (void) srv;
     150}
     151
     152static void remcons_set_pos(con_srv_t *srv, sysarg_t col, sysarg_t row)
     153{
     154        telnet_user_t *user = srv_to_user(srv);
     155
     156        telnet_user_update_cursor_x(user, col);
     157}
     158
     159static int remcons_get_pos(con_srv_t *srv, sysarg_t *col, sysarg_t *row)
     160{
     161        telnet_user_t *user = srv_to_user(srv);
     162
     163        *col = user->cursor_x;
     164        *row = 0;
     165
     166        return EOK;
     167}
     168
     169static int remcons_get_size(con_srv_t *srv, sysarg_t *cols, sysarg_t *rows)
     170{
     171        (void) srv;
     172
     173        *cols = 100;
     174        *rows = 1;
     175
     176        return EOK;
     177}
     178
     179static int remcons_get_color_cap(con_srv_t *srv, console_caps_t *ccaps)
     180{
     181        (void) srv;
     182        *ccaps = CONSOLE_CAP_NONE;
     183
     184        return EOK;
     185}
     186
     187static int remcons_get_event(con_srv_t *srv, cons_event_t *event)
     188{
     189        telnet_user_t *user = srv_to_user(srv);
     190        kbd_event_t kevent;
     191        int rc;
     192
     193        rc = telnet_user_get_next_keyboard_event(user, &kevent);
     194        if (rc != EOK) {
     195                /* XXX What? */
     196                memset(event, 0, sizeof(*event));
     197                return EOK;
     198        }
     199
     200        event->type = CEV_KEY;
     201        event->ev.key = kevent;
     202
     203        return EOK;
    188204}
    189205
     
    197213                return;
    198214        }
    199         async_answer_0(iid, EOK);
    200 
    201         telnet_user_log(user, "New client connected (%" PRIxn").", iid);
    202 
    203         /* Force character mode. */
    204         send(user->socket, (void *)telnet_force_character_mode_command,
    205             telnet_force_character_mode_command_count, 0);
    206215
    207216        /* Handle messages. */
    208         client_connection_message_loop(user);
    209 
    210         telnet_user_notify_client_disconnected(user);
    211         telnet_user_log(user, "Client disconnected (%" PRIxn").", iid);
     217        con_conn(iid, icall, &user->srvs);
    212218}
    213219
     
    231237                fibril_mutex_lock(&user->guard);
    232238                user->task_finished = true;
     239                user->srvs.aborted = true;
    233240                fibril_condvar_signal(&user->refcount_cv);
    234241                fibril_mutex_unlock(&user->guard);
     
    250257        fibril_mutex_lock(&user->guard);
    251258        user->task_finished = true;
     259        user->srvs.aborted = true;
    252260        fibril_condvar_signal(&user->refcount_cv);
    253261        fibril_mutex_unlock(&user->guard);
     
    272280static int network_user_fibril(void *arg)
    273281{
    274         int rc;
    275282        telnet_user_t *user = arg;
    276283
    277         rc = loc_service_register(user->service_name, &user->service_id);
     284        int rc = loc_service_register(user->service_name, &user->service_id);
    278285        if (rc != EOK) {
    279286                telnet_user_error(user, "Unable to register %s with loc: %s.",
     
    284291        telnet_user_log(user, "Service %s registerd with id %" PRIun ".",
    285292            user->service_name, user->service_id);
    286 
     293       
    287294        fid_t spawn_fibril = fibril_create(spawn_task_fibril, user);
    288295        assert(spawn_fibril);
    289296        fibril_add_ready(spawn_fibril);
    290 
     297       
    291298        /* Wait for all clients to exit. */
    292299        fibril_mutex_lock(&user->guard);
     
    295302                        closesocket(user->socket);
    296303                        user->socket_closed = true;
     304                        user->srvs.aborted = true;
    297305                        continue;
    298306                } else if (user->socket_closed) {
     
    304312        }
    305313        fibril_mutex_unlock(&user->guard);
    306 
     314       
    307315        rc = loc_service_unregister(user->service_id);
    308316        if (rc != EOK) {
     
    322330        int port = 2223;
    323331       
    324         int rc = loc_server_register(NAME, client_connection);
    325         if (rc < 0) {
    326                 fprintf(stderr, NAME ": Unable to register server: %s.\n",
    327                     str_error(rc));
    328                 return 1;
    329         }
    330 
     332        async_set_client_connection(client_connection);
     333        int rc = loc_server_register(NAME);
     334        if (rc != EOK) {
     335                fprintf(stderr, "%s: Unable to register server\n", NAME);
     336                return rc;
     337        }
     338       
    331339        struct sockaddr_in addr;
    332 
     340       
    333341        addr.sin_family = AF_INET;
    334342        addr.sin_port = htons(port);
    335 
     343       
    336344        rc = inet_pton(AF_INET, "127.0.0.1", (void *)
    337345            &addr.sin_addr.s_addr);
     
    363371
    364372        printf("%s: HelenOS Remote console service\n", NAME);
     373        task_retval(0);
    365374
    366375        while (true) {
     
    379388                assert(user);
    380389
     390                con_srvs_init(&user->srvs);
     391                user->srvs.ops = &con_ops;
     392                user->srvs.sarg = user;
     393                user->srvs.abort_timeout = 1000;
     394
     395                telnet_user_add(user);
     396
    381397                fid_t fid = fibril_create(network_user_fibril, user);
    382398                assert(fid);
Note: See TracChangeset for help on using the changeset viewer.