Changeset 99c2e9f3 in mainline


Ignore:
Timestamp:
2012-01-12T09:29:00Z (12 years ago)
Author:
Vojtech Horky <vojtechhorky@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
2a180307
Parents:
261bbdc
Message:

remcons: more refactoring

Location:
uspace/srv/hid/remcons
Files:
3 edited

Legend:

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

    r261bbdc r99c2e9f3  
    7474    sizeof(telnet_force_character_mode_command) / sizeof(telnet_cmd_t);
    7575
    76 /** Creates new keyboard event from given char.
    77  *
    78  * @param type Event type (press / release).
    79  * @param c Pressed character.
    80  */
    81 static kbd_event_t* new_kbd_event(kbd_event_type_t type, wchar_t c) {
    82         kbd_event_t *event = malloc(sizeof(kbd_event_t));
    83         assert(event);
    84 
    85         link_initialize(&event->link);
    86         event->type = type;
    87         event->c = c;
    88         event->mods = 0;
    89         event->key = (c == '\n' ? KC_ENTER : KC_A);
    90 
    91         return event;
    92 }
    9376
    9477/** Handling client requests (VFS and console interface).
     
    10184                ipc_call_t call;
    10285                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                 */
    10394                while (callid == 0) {
    10495                        callid = async_get_call_timeout(&call, 1000);
    10596
    106                         fibril_mutex_lock(&user->guard);
    107                         bool bail_out = user->socket_closed || user->task_finished;
    108                         fibril_mutex_unlock(&user->guard);
    109 
    110                         if (bail_out) {
     97                        if (telnet_user_is_zombie(user)) {
    11198                                if (callid != 0) {
    11299                                        async_answer_0(callid, EINTR);
     
    117104               
    118105                if (!IPC_GET_IMETHOD(call)) {
    119                         /* Clean-up. */
    120106                        return;
    121107                }
     
    129115                        break;
    130116                case CONSOLE_GET_EVENT: {
    131                         if (list_empty(&user->in_events.list)) {
    132                                 retry:
    133                                 if (user->socket_buffer_len <= user->socket_buffer_pos) {
    134                                         int recv_length = recv(user->socket, user->socket_buffer, BUFFER_SIZE, 0);
    135                                         if ((recv_length == 0) || (recv_length == ENOTCONN)) {
    136                                                 fibril_mutex_lock(&user->guard);
    137                                                 user->socket_closed = true;
    138                                                 fibril_mutex_unlock(&user->guard);
    139                                                 async_answer_0(callid, ENOENT);
    140                                                 return;
    141                                         }
    142                                         if (recv_length < 0) {
    143                                                 async_answer_0(callid, EINVAL);
    144                                                 return;
    145                                         }
    146                                         user->socket_buffer_len = recv_length;
    147                                         user->socket_buffer_pos = 0;
    148                                 }
    149                                 char data = user->socket_buffer[user->socket_buffer_pos++];
    150                                 if (data == 13) {
    151                                         data = 10;
    152                                 }
    153                                 if (data == 0)
    154                                         goto retry;
    155 
    156                                 kbd_event_t *down = new_kbd_event(KEY_PRESS, data);
    157                                 kbd_event_t *up = new_kbd_event(KEY_RELEASE, data);
    158                                 assert(down);
    159                                 assert(up);
    160                                 prodcons_produce(&user->in_events, &down->link);
    161                                 prodcons_produce(&user->in_events, &up->link);
    162                         }
    163 
    164 
    165                         link_t *link = prodcons_consume(&user->in_events);
    166                         kbd_event_t *event = list_get_instance(link, kbd_event_t, link);
    167                         async_answer_4(callid, EOK, event->type, event->key, event->mods, event->c);
    168                         free(event);
     117                        kbd_event_t event;
     118                        int rc = telnet_user_get_next_keyboard_event(user, &event);
     119                        if (rc != EOK) {
     120                                /* Silently ignore. */
     121                                async_answer_0(callid, EOK);
     122                                break;
     123                        }
     124                        async_answer_4(callid, EOK, event.type, event.key, event.mods, event.c);
    169125                        break;
    170126                }
     
    185141                                break;
    186142                        }
    187                         buf_converted = malloc(2 * size);
     143                        buf_converted = malloc(2 * size + 1);
    188144                        assert(buf_converted);
    189145                        int buf_converted_size = 0;
     
    197153                                }
    198154                        }
     155                        /* Add terminating zero for printing purposes. */
     156                        buf_converted[buf_converted_size] = 0;
     157
     158                        fibril_mutex_lock(&user->guard);
    199159                        rc = send(user->socket, buf_converted, buf_converted_size, 0);
     160                        fibril_mutex_unlock(&user->guard);
    200161                        free(buf);
    201162
     
    206167
    207168                        async_answer_1(callid, EOK, size);
    208 
    209169                        break;
    210170                }
     
    249209                return;
    250210        }
     211        async_answer_0(iid, EOK);
    251212
    252213        telnet_user_log(user, "New client connected (%" PRIxn").", iid);
    253 
    254         /* Accept the connection, increment reference. */
    255         async_answer_0(iid, EOK);
    256214
    257215        /* Force character mode. */
     
    259217            telnet_force_character_mode_command_count, 0);
    260218
     219        /* Handle messages. */
    261220        client_connection_message_loop(user);
    262221
    263         /* Announce user disconnection. */
    264222        telnet_user_notify_client_disconnected(user);
    265223        telnet_user_log(user, "Client disconnected (%" PRIxn").", iid);
  • uspace/srv/hid/remcons/user.c

    r261bbdc r99c2e9f3  
    172172}
    173173
     174/** Tell whether the launched task already exited and socket is already closed.
     175 *
     176 * @param user Telnet user in question.
     177 */
     178bool telnet_user_is_zombie(telnet_user_t *user)
     179{
     180        fibril_mutex_lock(&user->guard);
     181        bool zombie = user->socket_closed || user->task_finished;
     182        fibril_mutex_unlock(&user->guard);
     183
     184        return zombie;
     185}
     186
     187/** Receive next byte from a socket (use buffering.
     188 * We need to return the value via extra argument because the read byte
     189 * might be negative.
     190 */
     191static int telnet_user_recv_next_byte_no_lock(telnet_user_t *user, char *byte)
     192{
     193        /* No more buffered data? */
     194        if (user->socket_buffer_len <= user->socket_buffer_pos) {
     195                int recv_length = recv(user->socket, user->socket_buffer, BUFFER_SIZE, 0);
     196                if ((recv_length == 0) || (recv_length == ENOTCONN)) {
     197                        user->socket_closed = true;
     198                        return ENOENT;
     199                }
     200                if (recv_length < 0) {
     201                        return recv_length;
     202                }
     203                user->socket_buffer_len = recv_length;
     204                user->socket_buffer_pos = 0;
     205        }
     206
     207        *byte = user->socket_buffer[user->socket_buffer_pos++];
     208
     209        return EOK;
     210}
     211
     212/** Creates new keyboard event from given char.
     213 *
     214 * @param type Event type (press / release).
     215 * @param c Pressed character.
     216 */
     217static kbd_event_t* new_kbd_event(kbd_event_type_t type, wchar_t c) {
     218        kbd_event_t *event = malloc(sizeof(kbd_event_t));
     219        assert(event);
     220
     221        link_initialize(&event->link);
     222        event->type = type;
     223        event->c = c;
     224        event->mods = 0;
     225        event->key = (c == '\n' ? KC_ENTER : KC_A);
     226
     227        return event;
     228}
     229
     230int telnet_user_get_next_keyboard_event(telnet_user_t *user, kbd_event_t *event)
     231{
     232        fibril_mutex_lock(&user->guard);
     233        if (list_empty(&user->in_events.list)) {
     234                char next_byte = 0;
     235                /* Skip zeros, bail-out on error. */
     236                while (next_byte == 0) {
     237                        int rc = telnet_user_recv_next_byte_no_lock(user, &next_byte);
     238                        DEBUG("Got %d.\n", next_byte);
     239                        if (rc != EOK) {
     240                                fibril_mutex_unlock(&user->guard);
     241                                return rc;
     242                        }
     243                }
     244
     245                /* CR-LF conversions. */
     246                if (next_byte == 13) {
     247                        next_byte = 10;
     248                }
     249
     250                kbd_event_t *down = new_kbd_event(KEY_PRESS, next_byte);
     251                kbd_event_t *up = new_kbd_event(KEY_RELEASE, next_byte);
     252                assert(down);
     253                assert(up);
     254                prodcons_produce(&user->in_events, &down->link);
     255                prodcons_produce(&user->in_events, &up->link);
     256        }
     257
     258        link_t *link = prodcons_consume(&user->in_events);
     259        kbd_event_t *tmp = list_get_instance(link, kbd_event_t, link);
     260
     261        fibril_mutex_unlock(&user->guard);
     262
     263        *event = *tmp;
     264
     265        free(tmp);
     266
     267        return EOK;
     268}
    174269
    175270/**
  • uspace/srv/hid/remcons/user.h

    r261bbdc r99c2e9f3  
    4040#include "remcons.h"
    4141
    42 #define BUFFER_SIZE 1024
     42#define BUFFER_SIZE 32
    4343
    4444/** Representation of a connected (human) user. */
     
    7676void telnet_user_destroy(telnet_user_t *user);
    7777telnet_user_t *telnet_user_get_for_client_connection(service_id_t id);
     78bool telnet_user_is_zombie(telnet_user_t *user);
    7879void telnet_user_notify_client_disconnected(telnet_user_t *user);
     80int telnet_user_get_next_keyboard_event(telnet_user_t *user, kbd_event_t *event);
    7981
    8082/** Print informational message about connected user. */
Note: See TracChangeset for help on using the changeset viewer.