Changes in uspace/srv/hid/remcons/remcons.c [03e0a244:902f0906] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/srv/hid/remcons/remcons.c
r03e0a244 r902f0906 34 34 35 35 #include <async.h> 36 #include <errno.h> 37 #include <io/con_srv.h> 36 38 #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> 42 40 #include <str_error.h> 43 41 #include <loc.h> … … 45 43 #include <io/keycode.h> 46 44 #include <align.h> 47 #include <malloc.h>48 #include <as.h>49 45 #include <fibril_synch.h> 50 46 #include <task.h> … … 71 67 TELNET_IAC, TELNET_WONT, TELNET_LINEMODE 72 68 }; 69 73 70 static const size_t telnet_force_character_mode_command_count = 74 71 sizeof(telnet_force_character_mode_command) / sizeof(telnet_cmd_t); 75 72 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 } 73 static int remcons_open(con_srvs_t *, con_srv_t *); 74 static int remcons_close(con_srv_t *); 75 static int remcons_write(con_srv_t *, void *, size_t); 76 static void remcons_sync(con_srv_t *); 77 static void remcons_clear(con_srv_t *); 78 static void remcons_set_pos(con_srv_t *, sysarg_t col, sysarg_t row); 79 static int remcons_get_pos(con_srv_t *, sysarg_t *, sysarg_t *); 80 static int remcons_get_size(con_srv_t *, sysarg_t *, sysarg_t *); 81 static int remcons_get_color_cap(con_srv_t *, console_caps_t *); 82 static int remcons_get_event(con_srv_t *, cons_event_t *); 83 84 static 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 102 static telnet_user_t *srv_to_user(con_srv_t *srv) 103 { 104 return srv->srvs->sarg; 105 } 106 107 static 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 120 static 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 130 static 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 142 static void remcons_sync(con_srv_t *srv) 143 { 144 (void) srv; 145 } 146 147 static void remcons_clear(con_srv_t *srv) 148 { 149 (void) srv; 150 } 151 152 static 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 159 static 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 169 static 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 179 static 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 187 static 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; 188 204 } 189 205 … … 197 213 return; 198 214 } 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);206 215 207 216 /* 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); 212 218 } 213 219 … … 231 237 fibril_mutex_lock(&user->guard); 232 238 user->task_finished = true; 239 user->srvs.aborted = true; 233 240 fibril_condvar_signal(&user->refcount_cv); 234 241 fibril_mutex_unlock(&user->guard); … … 250 257 fibril_mutex_lock(&user->guard); 251 258 user->task_finished = true; 259 user->srvs.aborted = true; 252 260 fibril_condvar_signal(&user->refcount_cv); 253 261 fibril_mutex_unlock(&user->guard); … … 272 280 static int network_user_fibril(void *arg) 273 281 { 274 int rc;275 282 telnet_user_t *user = arg; 276 283 277 rc = loc_service_register(user->service_name, &user->service_id);284 int rc = loc_service_register(user->service_name, &user->service_id); 278 285 if (rc != EOK) { 279 286 telnet_user_error(user, "Unable to register %s with loc: %s.", … … 284 291 telnet_user_log(user, "Service %s registerd with id %" PRIun ".", 285 292 user->service_name, user->service_id); 286 293 287 294 fid_t spawn_fibril = fibril_create(spawn_task_fibril, user); 288 295 assert(spawn_fibril); 289 296 fibril_add_ready(spawn_fibril); 290 297 291 298 /* Wait for all clients to exit. */ 292 299 fibril_mutex_lock(&user->guard); … … 295 302 closesocket(user->socket); 296 303 user->socket_closed = true; 304 user->srvs.aborted = true; 297 305 continue; 298 306 } else if (user->socket_closed) { … … 304 312 } 305 313 fibril_mutex_unlock(&user->guard); 306 314 307 315 rc = loc_service_unregister(user->service_id); 308 316 if (rc != EOK) { … … 322 330 int port = 2223; 323 331 324 int rc = loc_server_register(NAME,client_connection);325 i f (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 331 339 struct sockaddr_in addr; 332 340 333 341 addr.sin_family = AF_INET; 334 342 addr.sin_port = htons(port); 335 343 336 344 rc = inet_pton(AF_INET, "127.0.0.1", (void *) 337 345 &addr.sin_addr.s_addr); … … 363 371 364 372 printf("%s: HelenOS Remote console service\n", NAME); 373 task_retval(0); 365 374 366 375 while (true) { … … 379 388 assert(user); 380 389 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 381 397 fid_t fid = fibril_create(network_user_fibril, user); 382 398 assert(fid);
Note:
See TracChangeset
for help on using the changeset viewer.