Changeset 99c2e9f3 in mainline
- Timestamp:
- 2012-01-12T09:29:00Z (13 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 2a180307
- Parents:
- 261bbdc
- Location:
- uspace/srv/hid/remcons
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/srv/hid/remcons/remcons.c
r261bbdc r99c2e9f3 74 74 sizeof(telnet_force_character_mode_command) / sizeof(telnet_cmd_t); 75 75 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 }93 76 94 77 /** Handling client requests (VFS and console interface). … … 101 84 ipc_call_t call; 102 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 */ 103 94 while (callid == 0) { 104 95 callid = async_get_call_timeout(&call, 1000); 105 96 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)) { 111 98 if (callid != 0) { 112 99 async_answer_0(callid, EINTR); … … 117 104 118 105 if (!IPC_GET_IMETHOD(call)) { 119 /* Clean-up. */120 106 return; 121 107 } … … 129 115 break; 130 116 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); 169 125 break; 170 126 } … … 185 141 break; 186 142 } 187 buf_converted = malloc(2 * size );143 buf_converted = malloc(2 * size + 1); 188 144 assert(buf_converted); 189 145 int buf_converted_size = 0; … … 197 153 } 198 154 } 155 /* Add terminating zero for printing purposes. */ 156 buf_converted[buf_converted_size] = 0; 157 158 fibril_mutex_lock(&user->guard); 199 159 rc = send(user->socket, buf_converted, buf_converted_size, 0); 160 fibril_mutex_unlock(&user->guard); 200 161 free(buf); 201 162 … … 206 167 207 168 async_answer_1(callid, EOK, size); 208 209 169 break; 210 170 } … … 249 209 return; 250 210 } 211 async_answer_0(iid, EOK); 251 212 252 213 telnet_user_log(user, "New client connected (%" PRIxn").", iid); 253 254 /* Accept the connection, increment reference. */255 async_answer_0(iid, EOK);256 214 257 215 /* Force character mode. */ … … 259 217 telnet_force_character_mode_command_count, 0); 260 218 219 /* Handle messages. */ 261 220 client_connection_message_loop(user); 262 221 263 /* Announce user disconnection. */264 222 telnet_user_notify_client_disconnected(user); 265 223 telnet_user_log(user, "Client disconnected (%" PRIxn").", iid); -
uspace/srv/hid/remcons/user.c
r261bbdc r99c2e9f3 172 172 } 173 173 174 /** Tell whether the launched task already exited and socket is already closed. 175 * 176 * @param user Telnet user in question. 177 */ 178 bool 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 */ 191 static 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 */ 217 static 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 230 int 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 } 174 269 175 270 /** -
uspace/srv/hid/remcons/user.h
r261bbdc r99c2e9f3 40 40 #include "remcons.h" 41 41 42 #define BUFFER_SIZE 102442 #define BUFFER_SIZE 32 43 43 44 44 /** Representation of a connected (human) user. */ … … 76 76 void telnet_user_destroy(telnet_user_t *user); 77 77 telnet_user_t *telnet_user_get_for_client_connection(service_id_t id); 78 bool telnet_user_is_zombie(telnet_user_t *user); 78 79 void telnet_user_notify_client_disconnected(telnet_user_t *user); 80 int telnet_user_get_next_keyboard_event(telnet_user_t *user, kbd_event_t *event); 79 81 80 82 /** Print informational message about connected user. */
Note:
See TracChangeset
for help on using the changeset viewer.