Changeset 787b65b in mainline
- Timestamp:
- 2012-01-12T07:47:51Z (13 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 30d4706
- Parents:
- 1870d81
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/srv/hid/remcons/remcons.c
r1870d81 r787b65b 84 84 int locsrv_connection_count; 85 85 bool socket_closed; 86 } client_t;87 88 static FIBRIL_MUTEX_INITIALIZE( clients_guard);89 static LIST_INITIALIZE( clients);86 } telnet_user_t; 87 88 static FIBRIL_MUTEX_INITIALIZE(users_guard); 89 static LIST_INITIALIZE(users); 90 90 91 91 /** Telnet commands to force character mode 92 92 * (redundant to be on the safe side). 93 93 * See 94 * http://stackoverflow.com/questions/273261/force-telnet- client-into-character-mode94 * http://stackoverflow.com/questions/273261/force-telnet-user-into-character-mode 95 95 * for discussion. 96 96 */ … … 103 103 sizeof(telnet_force_character_mode_command) / sizeof(telnet_cmd_t); 104 104 105 static client_t *client_create(int socket)106 { 107 static int client_counter = 0;108 109 client_t *client = malloc(sizeof(client_t));110 if ( client== NULL) {105 static telnet_user_t *telnet_user_create(int socket) 106 { 107 static int telnet_user_id_counter = 0; 108 109 telnet_user_t *user = malloc(sizeof(telnet_user_t)); 110 if (user == NULL) { 111 111 return NULL; 112 112 } 113 113 114 client->id = ++client_counter;115 116 int rc = asprintf(& client->service_name, "%s/telnet%d", NAMESPACE, client->id);114 user->id = ++telnet_user_id_counter; 115 116 int rc = asprintf(&user->service_name, "%s/telnet%d", NAMESPACE, user->id); 117 117 if (rc < 0) { 118 free( client);118 free(user); 119 119 return NULL; 120 120 } 121 121 122 client->socket = socket;123 client->service_id = (service_id_t) -1;124 prodcons_initialize(& client->in_events);125 link_initialize(& client->link);126 client->socket_buffer_len = 0;127 client->socket_buffer_pos = 0;128 129 fibril_condvar_initialize(& client->refcount_cv);130 fibril_mutex_initialize(& client->refcount_mutex);131 client->task_finished = false;132 client->socket_closed = false;133 client->locsrv_connection_count = 0;134 135 136 fibril_mutex_lock(& clients_guard);137 list_append(& client->link, &clients);138 fibril_mutex_unlock(& clients_guard);139 140 return client;141 } 142 143 static void client_destroy(client_t *client)144 { 145 assert( client);146 147 fibril_mutex_lock(& clients_guard);148 list_remove(& client->link);149 fibril_mutex_unlock(& clients_guard);150 151 free( client);152 } 153 154 static client_t *client_get_for_client_connection(service_id_t id)155 { 156 client_t *client= NULL;157 158 fibril_mutex_lock(& clients_guard);159 list_foreach( clients, link) {160 client_t *tmp = list_get_instance(link, client_t, link);122 user->socket = socket; 123 user->service_id = (service_id_t) -1; 124 prodcons_initialize(&user->in_events); 125 link_initialize(&user->link); 126 user->socket_buffer_len = 0; 127 user->socket_buffer_pos = 0; 128 129 fibril_condvar_initialize(&user->refcount_cv); 130 fibril_mutex_initialize(&user->refcount_mutex); 131 user->task_finished = false; 132 user->socket_closed = false; 133 user->locsrv_connection_count = 0; 134 135 136 fibril_mutex_lock(&users_guard); 137 list_append(&user->link, &users); 138 fibril_mutex_unlock(&users_guard); 139 140 return user; 141 } 142 143 static void telnet_user_destroy(telnet_user_t *user) 144 { 145 assert(user); 146 147 fibril_mutex_lock(&users_guard); 148 list_remove(&user->link); 149 fibril_mutex_unlock(&users_guard); 150 151 free(user); 152 } 153 154 static telnet_user_t *telnet_user_get_for_client_connection(service_id_t id) 155 { 156 telnet_user_t *user = NULL; 157 158 fibril_mutex_lock(&users_guard); 159 list_foreach(users, link) { 160 telnet_user_t *tmp = list_get_instance(link, telnet_user_t, link); 161 161 if (tmp->service_id == id) { 162 client= tmp;163 break; 164 } 165 } 166 if ( client== NULL) {167 fibril_mutex_unlock(& clients_guard);162 user = tmp; 163 break; 164 } 165 } 166 if (user == NULL) { 167 fibril_mutex_unlock(&users_guard); 168 168 return NULL; 169 169 } 170 170 171 client_t *tmp = client;171 telnet_user_t *tmp = user; 172 172 fibril_mutex_lock(&tmp->refcount_mutex); 173 client->locsrv_connection_count++;173 user->locsrv_connection_count++; 174 174 175 175 /* 176 * Refuse to return clientwhose task already finished or when176 * Refuse to return user whose task already finished or when 177 177 * the socket is already closed(). 178 178 */ 179 if ( client->task_finished || client->socket_closed) {180 client= NULL;181 client->locsrv_connection_count--;179 if (user->task_finished || user->socket_closed) { 180 user = NULL; 181 user->locsrv_connection_count--; 182 182 } 183 183 … … 185 185 186 186 187 fibril_mutex_unlock(& clients_guard);188 189 return client;187 fibril_mutex_unlock(&users_guard); 188 189 return user; 190 190 } 191 191 … … 205 205 } 206 206 207 static void client_connection_message_loop( client_t *client)207 static void client_connection_message_loop(telnet_user_t *user) 208 208 { 209 209 while (true) { … … 213 213 callid = async_get_call_timeout(&call, 1000); 214 214 215 fibril_mutex_lock(& client->refcount_mutex);216 bool bail_out = client->socket_closed || client->task_finished;217 fibril_mutex_unlock(& client->refcount_mutex);215 fibril_mutex_lock(&user->refcount_mutex); 216 bool bail_out = user->socket_closed || user->task_finished; 217 fibril_mutex_unlock(&user->refcount_mutex); 218 218 219 219 if (bail_out) { … … 238 238 break; 239 239 case CONSOLE_GET_EVENT: { 240 if (list_empty(& client->in_events.list)) {240 if (list_empty(&user->in_events.list)) { 241 241 retry: 242 if ( client->socket_buffer_len <= client->socket_buffer_pos) {243 int recv_length = recv( client->socket, client->socket_buffer, BUFFER_SIZE, 0);242 if (user->socket_buffer_len <= user->socket_buffer_pos) { 243 int recv_length = recv(user->socket, user->socket_buffer, BUFFER_SIZE, 0); 244 244 if ((recv_length == 0) || (recv_length == ENOTCONN)) { 245 fibril_mutex_lock(& client->refcount_mutex);246 client->socket_closed = true;247 fibril_mutex_unlock(& client->refcount_mutex);245 fibril_mutex_lock(&user->refcount_mutex); 246 user->socket_closed = true; 247 fibril_mutex_unlock(&user->refcount_mutex); 248 248 async_answer_0(callid, ENOENT); 249 249 return; … … 253 253 return; 254 254 } 255 client->socket_buffer_len = recv_length;256 client->socket_buffer_pos = 0;255 user->socket_buffer_len = recv_length; 256 user->socket_buffer_pos = 0; 257 257 } 258 char data = client->socket_buffer[client->socket_buffer_pos++];258 char data = user->socket_buffer[user->socket_buffer_pos++]; 259 259 if (data == 13) { 260 260 data = 10; … … 267 267 assert(down); 268 268 assert(up); 269 prodcons_produce(& client->in_events, &down->link);270 prodcons_produce(& client->in_events, &up->link);269 prodcons_produce(&user->in_events, &down->link); 270 prodcons_produce(&user->in_events, &up->link); 271 271 } 272 272 273 273 274 link_t *link = prodcons_consume(& client->in_events);274 link_t *link = prodcons_consume(&user->in_events); 275 275 kbd_event_t *event = list_get_instance(link, kbd_event_t, link); 276 276 async_answer_4(callid, EOK, event->type, event->key, event->mods, event->c); … … 306 306 } 307 307 } 308 rc = send( client->socket, buf_converted, buf_converted_size, 0);308 rc = send(user->socket, buf_converted, buf_converted_size, 0); 309 309 free(buf); 310 310 … … 352 352 static void client_connection(ipc_callid_t iid, ipc_call_t *icall, void *arg) 353 353 { 354 /* Find the client. */355 client_t *client = client_get_for_client_connection(IPC_GET_ARG1(*icall));356 if ( client== NULL) {354 /* Find the user. */ 355 telnet_user_t *user = telnet_user_get_for_client_connection(IPC_GET_ARG1(*icall)); 356 if (user == NULL) { 357 357 async_answer_0(iid, ENOENT); 358 358 return; 359 359 } 360 360 361 printf("New client for service %s.\n", client->service_name);361 printf("New user for service %s.\n", user->service_name); 362 362 363 363 /* Accept the connection, increment reference. */ … … 365 365 366 366 /* Force character mode. */ 367 send( client->socket, (void *)telnet_force_character_mode_command,367 send(user->socket, (void *)telnet_force_character_mode_command, 368 368 telnet_force_character_mode_command_count, 0); 369 369 370 client_connection_message_loop( client);371 372 /* Announce clientdisconnection. */373 fibril_mutex_lock(& client->refcount_mutex);374 client->locsrv_connection_count--;375 fibril_condvar_signal(& client->refcount_cv);376 fibril_mutex_unlock(& client->refcount_mutex);370 client_connection_message_loop(user); 371 372 /* Announce user disconnection. */ 373 fibril_mutex_lock(&user->refcount_mutex); 374 user->locsrv_connection_count--; 375 fibril_condvar_signal(&user->refcount_cv); 376 fibril_mutex_unlock(&user->refcount_mutex); 377 377 } 378 378 379 379 static int spawn_task_fibril(void *arg) 380 380 { 381 client_t *client= arg;381 telnet_user_t *user = arg; 382 382 int rc; 383 383 384 384 char term[LOC_NAME_MAXLEN]; 385 snprintf(term, LOC_NAME_MAXLEN, "%s/%s", "/loc", client->service_name);385 snprintf(term, LOC_NAME_MAXLEN, "%s/%s", "/loc", user->service_name); 386 386 387 387 task_id_t task; … … 390 390 printf("%s: Error spawning %s -w %s %s (%s)\n", NAME, 391 391 APP_GETTERM, term, "/app/bdsh", str_error(rc)); 392 fibril_mutex_lock(& client->refcount_mutex);393 client->task_finished = true;394 fibril_condvar_signal(& client->refcount_cv);395 fibril_mutex_unlock(& client->refcount_mutex);392 fibril_mutex_lock(&user->refcount_mutex); 393 user->task_finished = true; 394 fibril_condvar_signal(&user->refcount_cv); 395 fibril_mutex_unlock(&user->refcount_mutex); 396 396 return EOK; 397 397 } 398 398 399 fibril_mutex_lock(& client->refcount_mutex);400 client->task_id = task;401 fibril_mutex_unlock(& client->refcount_mutex);399 fibril_mutex_lock(&user->refcount_mutex); 400 user->task_id = task; 401 fibril_mutex_unlock(&user->refcount_mutex); 402 402 403 403 task_exit_t task_exit; … … 407 407 408 408 /* Announce destruction. */ 409 fibril_mutex_lock(& client->refcount_mutex);410 client->task_finished = true;411 fibril_condvar_signal(& client->refcount_cv);412 fibril_mutex_unlock(& client->refcount_mutex);409 fibril_mutex_lock(&user->refcount_mutex); 410 user->task_finished = true; 411 fibril_condvar_signal(&user->refcount_cv); 412 fibril_mutex_unlock(&user->refcount_mutex); 413 413 414 414 return EOK; 415 415 } 416 416 417 static bool client_can_be_destroyed_no_lock(client_t *client)418 { 419 return client->task_finished && client->socket_closed &&420 ( client->locsrv_connection_count == 0);421 } 422 423 static int network_ client_fibril(void *arg)417 static bool user_can_be_destroyed_no_lock(telnet_user_t *user) 418 { 419 return user->task_finished && user->socket_closed && 420 (user->locsrv_connection_count == 0); 421 } 422 423 static int network_user_fibril(void *arg) 424 424 { 425 425 int rc; 426 client_t *client= arg;427 428 rc = loc_service_register( client->service_name, &client->service_id);426 telnet_user_t *user = arg; 427 428 rc = loc_service_register(user->service_name, &user->service_id); 429 429 if (rc != EOK) { 430 430 fprintf(stderr, "%s: Unable to register device %s\n", NAME, 431 client->service_name);431 user->service_name); 432 432 return EOK; 433 433 } 434 printf("Service %s registered as %" PRIun "\n", client->service_name,435 client->service_id);436 437 fid_t spawn_fibril = fibril_create(spawn_task_fibril, client);434 printf("Service %s registered as %" PRIun "\n", user->service_name, 435 user->service_id); 436 437 fid_t spawn_fibril = fibril_create(spawn_task_fibril, user); 438 438 assert(spawn_fibril); 439 439 fibril_add_ready(spawn_fibril); 440 440 441 441 /* Wait for all clients to exit. */ 442 fibril_mutex_lock(& client->refcount_mutex);443 while (! client_can_be_destroyed_no_lock(client)) {444 if ( client->task_finished) {445 closesocket( client->socket);446 client->socket_closed = true;442 fibril_mutex_lock(&user->refcount_mutex); 443 while (!user_can_be_destroyed_no_lock(user)) { 444 if (user->task_finished) { 445 closesocket(user->socket); 446 user->socket_closed = true; 447 447 continue; 448 } else if ( client->socket_closed) {449 if ( client->task_id != 0) {450 task_kill( client->task_id);448 } else if (user->socket_closed) { 449 if (user->task_id != 0) { 450 task_kill(user->task_id); 451 451 } 452 452 } 453 fibril_condvar_wait_timeout(& client->refcount_cv, &client->refcount_mutex, 1000);454 } 455 fibril_mutex_unlock(& client->refcount_mutex);456 457 rc = loc_service_unregister( client->service_id);453 fibril_condvar_wait_timeout(&user->refcount_cv, &user->refcount_mutex, 1000); 454 } 455 fibril_mutex_unlock(&user->refcount_mutex); 456 457 rc = loc_service_unregister(user->service_id); 458 458 if (rc != EOK) { 459 fprintf(stderr, "Warning: failed to unregister %s: %s\n", client->service_name, str_error(rc));460 } 461 462 printf("Destroying service %s.\n", client->service_name);463 client_destroy(client);459 fprintf(stderr, "Warning: failed to unregister %s: %s\n", user->service_name, str_error(rc)); 460 } 461 462 printf("Destroying service %s.\n", user->service_name); 463 telnet_user_destroy(user); 464 464 465 465 return EOK; … … 523 523 } 524 524 525 client_t *client = client_create(conn_sd);526 assert( client);527 528 fid_t fid = fibril_create(network_ client_fibril, client);525 telnet_user_t *user = telnet_user_create(conn_sd); 526 assert(user); 527 528 fid_t fid = fibril_create(network_user_fibril, user); 529 529 assert(fid); 530 530 fibril_add_ready(fid);
Note:
See TracChangeset
for help on using the changeset viewer.