source: mainline/uspace/srv/locsrv/locsrv.c@ c657bd7

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since c657bd7 was adb1ae9, checked in by Jakub Jermar <jakub@…>, 8 years ago

Answer IPC only when there will be no blocking

This is necessary so that a parallel exchange is not handled by a
connection fibril which is still itself waiting for IPC or resources.

  • Property mode set to 100644
File size: 35.1 KB
RevLine 
[15f3c3f]1/*
2 * Copyright (c) 2007 Josef Cejka
3 * Copyright (c) 2011 Jiri Svoboda
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 *
10 * - Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * - Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * - The name of the author may not be used to endorse or promote products
16 * derived from this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */
29
30/**
31 * @defgroup loc Location Service.
32 * @brief HelenOS location service.
33 * @{
34 */
35
36/** @file
37 */
38
39#include <ipc/services.h>
40#include <ns.h>
41#include <async.h>
42#include <stdio.h>
43#include <errno.h>
[3e6a98c5]44#include <stdbool.h>
[15f3c3f]45#include <fibril_synch.h>
[cce8a83]46#include <macros.h>
[15f3c3f]47#include <stdlib.h>
48#include <str.h>
49#include <ipc/loc.h>
50#include <assert.h>
51
[cc574511]52#include "category.h"
[32d96e1]53#include "locsrv.h"
[cc574511]54
[15f3c3f]55#define NAME "loc"
56#define NULL_SERVICES 256
57
[77a69ea]58/** Callback session */
59typedef struct {
60 link_t cb_sess_list;
61 async_sess_t *sess;
62} cb_sess_t;
63
[15f3c3f]64LIST_INITIALIZE(services_list);
65LIST_INITIALIZE(namespaces_list);
66LIST_INITIALIZE(servers_list);
67
68/* Locking order:
69 * servers_list_mutex
70 * services_list_mutex
71 * (loc_server_t *)->services_mutex
72 * create_id_mutex
73 **/
74
[d0dd7b5]75FIBRIL_MUTEX_INITIALIZE(services_list_mutex);
[15f3c3f]76static FIBRIL_CONDVAR_INITIALIZE(services_list_cv);
77static FIBRIL_MUTEX_INITIALIZE(servers_list_mutex);
78static FIBRIL_MUTEX_INITIALIZE(create_id_mutex);
79static FIBRIL_MUTEX_INITIALIZE(null_services_mutex);
80
81static service_id_t last_id = 0;
82static loc_service_t *null_services[NULL_SERVICES];
83
84/*
85 * Dummy list for null services. This is necessary so that null services can
86 * be used just as any other services, e.g. in loc_service_unregister_core().
87 */
88static LIST_INITIALIZE(dummy_null_services);
89
[cc574511]90/** Service directory ogranized by categories (yellow pages) */
91static categ_dir_t cdir;
92
[12f9f0d0]93static FIBRIL_MUTEX_INITIALIZE(callback_sess_mutex);
[77a69ea]94static LIST_INITIALIZE(callback_sess_list);
[12f9f0d0]95
[cc574511]96service_id_t loc_create_id(void)
[15f3c3f]97{
98 /* TODO: allow reusing old ids after their unregistration
99 * and implement some version of LRU algorithm, avoid overflow
100 */
101
102 fibril_mutex_lock(&create_id_mutex);
103 last_id++;
104 fibril_mutex_unlock(&create_id_mutex);
105
106 return last_id;
107}
108
109/** Convert fully qualified service name to namespace and service name.
110 *
111 * A fully qualified service name can be either a plain service name
112 * (then the namespace is considered to be an empty string) or consist
113 * of two components separated by a slash. No more than one slash
114 * is allowed.
115 *
116 */
117static bool loc_fqsn_split(const char *fqsn, char **ns_name, char **name)
118{
119 size_t cnt = 0;
120 size_t slash_offset = 0;
121 size_t slash_after = 0;
122
123 size_t offset = 0;
124 size_t offset_prev = 0;
125 wchar_t c;
126
127 while ((c = str_decode(fqsn, &offset, STR_NO_LIMIT)) != 0) {
128 if (c == '/') {
129 cnt++;
130 slash_offset = offset_prev;
131 slash_after = offset;
132 }
133 offset_prev = offset;
134 }
135
136 /* More than one slash */
137 if (cnt > 1)
138 return false;
139
140 /* No slash -> namespace is empty */
141 if (cnt == 0) {
142 *ns_name = str_dup("");
143 if (*ns_name == NULL)
144 return false;
145
146 *name = str_dup(fqsn);
147 if (*name == NULL) {
148 free(*ns_name);
149 return false;
150 }
151
152 if (str_cmp(*name, "") == 0) {
153 free(*name);
154 free(*ns_name);
155 return false;
156 }
157
158 return true;
159 }
160
161 /* Exactly one slash */
162 *ns_name = str_ndup(fqsn, slash_offset);
163 if (*ns_name == NULL)
164 return false;
165
166 *name = str_dup(fqsn + slash_after);
167 if (*name == NULL) {
168 free(*ns_name);
169 return false;
170 }
171
172 if (str_cmp(*name, "") == 0) {
173 free(*name);
174 free(*ns_name);
175 return false;
176 }
177
178 return true;
179}
180
181/** Find namespace with given name. */
182static loc_namespace_t *loc_namespace_find_name(const char *name)
183{
184 assert(fibril_mutex_is_locked(&services_list_mutex));
185
[feeac0d]186 list_foreach(namespaces_list, namespaces, loc_namespace_t, namespace) {
[15f3c3f]187 if (str_cmp(namespace->name, name) == 0)
188 return namespace;
189 }
190
191 return NULL;
192}
193
194/** Find namespace with given ID.
195 *
196 * @todo: use hash table
197 *
198 */
199static loc_namespace_t *loc_namespace_find_id(service_id_t id)
200{
201 assert(fibril_mutex_is_locked(&services_list_mutex));
202
[feeac0d]203 list_foreach(namespaces_list, namespaces, loc_namespace_t, namespace) {
[15f3c3f]204 if (namespace->id == id)
205 return namespace;
206 }
207
208 return NULL;
209}
210
211/** Find service with given name. */
212static loc_service_t *loc_service_find_name(const char *ns_name,
213 const char *name)
214{
215 assert(fibril_mutex_is_locked(&services_list_mutex));
216
[feeac0d]217 list_foreach(services_list, services, loc_service_t, service) {
[15f3c3f]218 if ((str_cmp(service->namespace->name, ns_name) == 0)
219 && (str_cmp(service->name, name) == 0))
220 return service;
221 }
222
223 return NULL;
224}
225
226/** Find service with given ID.
227 *
228 * @todo: use hash table
229 *
230 */
231static loc_service_t *loc_service_find_id(service_id_t id)
232{
233 assert(fibril_mutex_is_locked(&services_list_mutex));
234
[feeac0d]235 list_foreach(services_list, services, loc_service_t, service) {
[15f3c3f]236 if (service->id == id)
237 return service;
238 }
239
240 return NULL;
241}
242
243/** Create a namespace (if not already present). */
244static loc_namespace_t *loc_namespace_create(const char *ns_name)
245{
246 loc_namespace_t *namespace;
247
248 assert(fibril_mutex_is_locked(&services_list_mutex));
249
250 namespace = loc_namespace_find_name(ns_name);
251 if (namespace != NULL)
252 return namespace;
253
254 namespace = (loc_namespace_t *) malloc(sizeof(loc_namespace_t));
255 if (namespace == NULL)
256 return NULL;
257
258 namespace->name = str_dup(ns_name);
259 if (namespace->name == NULL) {
260 free(namespace);
261 return NULL;
262 }
263
264 namespace->id = loc_create_id();
265 namespace->refcnt = 0;
266
267 /*
268 * Insert new namespace into list of registered namespaces
269 */
270 list_append(&(namespace->namespaces), &namespaces_list);
271
272 return namespace;
273}
274
275/** Destroy a namespace (if it is no longer needed). */
276static void loc_namespace_destroy(loc_namespace_t *namespace)
277{
278 assert(fibril_mutex_is_locked(&services_list_mutex));
279
280 if (namespace->refcnt == 0) {
281 list_remove(&(namespace->namespaces));
282
283 free(namespace->name);
284 free(namespace);
285 }
286}
287
288/** Increase namespace reference count by including service. */
289static void loc_namespace_addref(loc_namespace_t *namespace,
290 loc_service_t *service)
291{
292 assert(fibril_mutex_is_locked(&services_list_mutex));
293
294 service->namespace = namespace;
295 namespace->refcnt++;
296}
297
298/** Decrease namespace reference count. */
299static void loc_namespace_delref(loc_namespace_t *namespace)
300{
301 assert(fibril_mutex_is_locked(&services_list_mutex));
302
303 namespace->refcnt--;
304 loc_namespace_destroy(namespace);
305}
306
307/** Unregister service and free it. */
308static void loc_service_unregister_core(loc_service_t *service)
309{
310 assert(fibril_mutex_is_locked(&services_list_mutex));
[d0dd7b5]311 assert(fibril_mutex_is_locked(&cdir.mutex));
312
[15f3c3f]313 loc_namespace_delref(service->namespace);
314 list_remove(&(service->services));
315 list_remove(&(service->server_services));
316
[d0dd7b5]317 /* Remove service from all categories. */
318 while (!list_empty(&service->cat_memb)) {
319 link_t *link = list_first(&service->cat_memb);
320 svc_categ_t *memb = list_get_instance(link, svc_categ_t,
321 svc_link);
[69d25e2]322 category_t *cat = memb->cat;
323
324 fibril_mutex_lock(&cat->mutex);
[d0dd7b5]325 category_remove_service(memb);
[69d25e2]326 fibril_mutex_unlock(&cat->mutex);
[d0dd7b5]327 }
328
[15f3c3f]329 free(service->name);
330 free(service);
331}
332
333/**
334 * Read info about new server and add it into linked list of registered
335 * servers.
336 */
337static loc_server_t *loc_server_register(void)
338{
339 ipc_call_t icall;
340 ipc_callid_t iid = async_get_call(&icall);
341
342 if (IPC_GET_IMETHOD(icall) != LOC_SERVER_REGISTER) {
343 async_answer_0(iid, EREFUSED);
344 return NULL;
345 }
346
347 loc_server_t *server =
348 (loc_server_t *) malloc(sizeof(loc_server_t));
349 if (server == NULL) {
350 async_answer_0(iid, ENOMEM);
351 return NULL;
352 }
353
354 /*
355 * Get server name
356 */
357 int rc = async_data_write_accept((void **) &server->name, true, 0,
358 LOC_NAME_MAXLEN, 0, NULL);
359 if (rc != EOK) {
360 free(server);
361 async_answer_0(iid, rc);
362 return NULL;
363 }
364
365 /*
366 * Create connection to the server
367 */
368 server->sess = async_callback_receive(EXCHANGE_SERIALIZE);
369 if (!server->sess) {
370 free(server->name);
371 free(server);
372 async_answer_0(iid, ENOTSUP);
373 return NULL;
374 }
375
376 /*
377 * Initialize mutex for list of services
378 * supplied by this server
379 */
380 fibril_mutex_initialize(&server->services_mutex);
381
382 /*
383 * Initialize list of supplied services
384 */
385 list_initialize(&server->services);
386 link_initialize(&server->servers);
387
388 fibril_mutex_lock(&servers_list_mutex);
389
390 /* TODO:
391 * Check that no server with name equal to
392 * server->name is registered
393 */
394
395 /*
396 * Insert new server into list of registered servers
397 */
398 list_append(&(server->servers), &servers_list);
399 fibril_mutex_unlock(&servers_list_mutex);
400
401 async_answer_0(iid, EOK);
402
403 return server;
404}
405
406/**
407 * Unregister server, unregister all its services and free server
408 * structure.
409 *
410 */
411static int loc_server_unregister(loc_server_t *server)
412{
413 if (server == NULL)
[8a637a4]414 return EEXIST;
[15f3c3f]415
416 fibril_mutex_lock(&servers_list_mutex);
417
418 if (server->sess)
419 async_hangup(server->sess);
420
421 /* Remove it from list of servers */
422 list_remove(&(server->servers));
423
424 /* Unregister all its services */
425 fibril_mutex_lock(&services_list_mutex);
426 fibril_mutex_lock(&server->services_mutex);
[d0dd7b5]427 fibril_mutex_lock(&cdir.mutex);
[15f3c3f]428
429 while (!list_empty(&server->services)) {
430 loc_service_t *service = list_get_instance(
431 list_first(&server->services), loc_service_t,
432 server_services);
433 loc_service_unregister_core(service);
434 }
435
[d0dd7b5]436 fibril_mutex_unlock(&cdir.mutex);
[15f3c3f]437 fibril_mutex_unlock(&server->services_mutex);
438 fibril_mutex_unlock(&services_list_mutex);
439 fibril_mutex_unlock(&servers_list_mutex);
440
441 /* Free name and server */
442 if (server->name != NULL)
443 free(server->name);
444
445 free(server);
446
[3a9cf35]447 loc_category_change_event();
[15f3c3f]448 return EOK;
449}
450
451/** Register service
452 *
453 */
454static void loc_service_register(ipc_callid_t iid, ipc_call_t *icall,
455 loc_server_t *server)
456{
457 if (server == NULL) {
458 async_answer_0(iid, EREFUSED);
459 return;
460 }
461
462 /* Create new service entry */
463 loc_service_t *service =
464 (loc_service_t *) malloc(sizeof(loc_service_t));
465 if (service == NULL) {
466 async_answer_0(iid, ENOMEM);
467 return;
468 }
469
470 /* Get fqsn */
471 char *fqsn;
472 int rc = async_data_write_accept((void **) &fqsn, true, 0,
473 LOC_NAME_MAXLEN, 0, NULL);
474 if (rc != EOK) {
475 free(service);
476 async_answer_0(iid, rc);
477 return;
478 }
479
480 char *ns_name;
481 if (!loc_fqsn_split(fqsn, &ns_name, &service->name)) {
482 free(fqsn);
483 free(service);
484 async_answer_0(iid, EINVAL);
485 return;
486 }
487
488 free(fqsn);
489
490 fibril_mutex_lock(&services_list_mutex);
491
492 loc_namespace_t *namespace = loc_namespace_create(ns_name);
493 free(ns_name);
494 if (namespace == NULL) {
495 fibril_mutex_unlock(&services_list_mutex);
496 free(service->name);
497 free(service);
498 async_answer_0(iid, ENOMEM);
499 return;
500 }
501
502 link_initialize(&service->services);
503 link_initialize(&service->server_services);
[d0dd7b5]504 list_initialize(&service->cat_memb);
[15f3c3f]505
506 /* Check that service is not already registered */
507 if (loc_service_find_name(namespace->name, service->name) != NULL) {
508 printf("%s: Service '%s/%s' already registered\n", NAME,
509 namespace->name, service->name);
510 loc_namespace_destroy(namespace);
511 fibril_mutex_unlock(&services_list_mutex);
512 free(service->name);
513 free(service);
[8a637a4]514 async_answer_0(iid, EEXIST);
[15f3c3f]515 return;
516 }
517
518 /* Get unique service ID */
519 service->id = loc_create_id();
520
521 loc_namespace_addref(namespace, service);
522 service->server = server;
523
524 /* Insert service into list of all services */
525 list_append(&service->services, &services_list);
526
527 /* Insert service into list of services supplied by one server */
528 fibril_mutex_lock(&service->server->services_mutex);
529
530 list_append(&service->server_services, &service->server->services);
531
532 fibril_mutex_unlock(&service->server->services_mutex);
533 fibril_condvar_broadcast(&services_list_cv);
534 fibril_mutex_unlock(&services_list_mutex);
535
536 async_answer_1(iid, EOK, service->id);
537}
538
539/**
540 *
541 */
[d0dd7b5]542static void loc_service_unregister(ipc_callid_t iid, ipc_call_t *icall,
[15f3c3f]543 loc_server_t *server)
544{
[d0dd7b5]545 loc_service_t *svc;
546
547 fibril_mutex_lock(&services_list_mutex);
548 svc = loc_service_find_id(IPC_GET_ARG1(*icall));
549 if (svc == NULL) {
550 fibril_mutex_unlock(&services_list_mutex);
551 async_answer_0(iid, ENOENT);
552 return;
553 }
554
555 fibril_mutex_lock(&cdir.mutex);
556 loc_service_unregister_core(svc);
557 fibril_mutex_unlock(&cdir.mutex);
558 fibril_mutex_unlock(&services_list_mutex);
[3a9cf35]559
[adb1ae9]560 /*
561 * First send out all notifications and only then answer the request.
562 * Otherwise the current fibril might block and transitively wait for
563 * the completion of requests that are routed to it via an IPC loop.
564 */
[3a9cf35]565 loc_category_change_event();
[adb1ae9]566 async_answer_0(iid, EOK);
[15f3c3f]567}
568
[763e0cd]569static void loc_category_get_name(ipc_callid_t iid, ipc_call_t *icall)
570{
571 ipc_callid_t callid;
572 size_t size;
573 size_t act_size;
574 category_t *cat;
575
576 if (!async_data_read_receive(&callid, &size)) {
577 async_answer_0(callid, EREFUSED);
578 async_answer_0(iid, EREFUSED);
579 return;
580 }
581
582 fibril_mutex_lock(&cdir.mutex);
583
584 cat = category_get(&cdir, IPC_GET_ARG1(*icall));
585 if (cat == NULL) {
586 fibril_mutex_unlock(&cdir.mutex);
587 async_answer_0(callid, ENOENT);
588 async_answer_0(iid, ENOENT);
589 return;
590 }
591
592 act_size = str_size(cat->name);
593 if (act_size > size) {
594 fibril_mutex_unlock(&cdir.mutex);
595 async_answer_0(callid, EOVERFLOW);
596 async_answer_0(iid, EOVERFLOW);
597 return;
598 }
599
600 sysarg_t retval = async_data_read_finalize(callid, cat->name,
601 min(size, act_size));
602
603 fibril_mutex_unlock(&cdir.mutex);
604
605 async_answer_0(iid, retval);
606}
607
[cce8a83]608static void loc_service_get_name(ipc_callid_t iid, ipc_call_t *icall)
609{
610 ipc_callid_t callid;
611 size_t size;
612 size_t act_size;
613 loc_service_t *svc;
[77a69ea]614 char *fqn;
[cce8a83]615
616 if (!async_data_read_receive(&callid, &size)) {
617 async_answer_0(callid, EREFUSED);
618 async_answer_0(iid, EREFUSED);
619 return;
620 }
621
622 fibril_mutex_lock(&services_list_mutex);
623
624 svc = loc_service_find_id(IPC_GET_ARG1(*icall));
625 if (svc == NULL) {
626 fibril_mutex_unlock(&services_list_mutex);
627 async_answer_0(callid, ENOENT);
628 async_answer_0(iid, ENOENT);
629 return;
630 }
631
[77a69ea]632 if (asprintf(&fqn, "%s/%s", svc->namespace->name, svc->name) < 0) {
633 fibril_mutex_unlock(&services_list_mutex);
634 async_answer_0(callid, ENOMEM);
635 async_answer_0(iid, ENOMEM);
636 return;
637 }
638
639 act_size = str_size(fqn);
[cce8a83]640 if (act_size > size) {
[77a69ea]641 free(fqn);
[cce8a83]642 fibril_mutex_unlock(&services_list_mutex);
643 async_answer_0(callid, EOVERFLOW);
644 async_answer_0(iid, EOVERFLOW);
645 return;
646 }
647
[77a69ea]648 sysarg_t retval = async_data_read_finalize(callid, fqn,
[cce8a83]649 min(size, act_size));
[77a69ea]650 free(fqn);
[cce8a83]651
652 fibril_mutex_unlock(&services_list_mutex);
653
654 async_answer_0(iid, retval);
655}
656
[a3fcfba]657static void loc_service_get_server_name(ipc_callid_t iid, ipc_call_t *icall)
658{
659 ipc_callid_t callid;
660 size_t size;
661 size_t act_size;
662 loc_service_t *svc;
663
664 if (!async_data_read_receive(&callid, &size)) {
665 async_answer_0(callid, EREFUSED);
666 async_answer_0(iid, EREFUSED);
667 return;
668 }
669
670 fibril_mutex_lock(&services_list_mutex);
671
672 svc = loc_service_find_id(IPC_GET_ARG1(*icall));
673 if (svc == NULL) {
674 fibril_mutex_unlock(&services_list_mutex);
675 async_answer_0(callid, ENOENT);
676 async_answer_0(iid, ENOENT);
677 return;
678 }
679
680 if (svc->server == NULL) {
681 fibril_mutex_unlock(&services_list_mutex);
682 async_answer_0(callid, EINVAL);
683 async_answer_0(iid, EINVAL);
684 return;
685 }
686
687 act_size = str_size(svc->server->name);
688 if (act_size > size) {
689 fibril_mutex_unlock(&services_list_mutex);
690 async_answer_0(callid, EOVERFLOW);
691 async_answer_0(iid, EOVERFLOW);
692 return;
693 }
694
695 sysarg_t retval = async_data_read_finalize(callid, svc->server->name,
696 min(size, act_size));
697
698 fibril_mutex_unlock(&services_list_mutex);
699
700 async_answer_0(iid, retval);
701}
702
[15f3c3f]703/** Connect client to the service.
704 *
705 * Find server supplying requested service and forward
706 * the message to it.
707 *
708 */
[f9b2cb4c]709static void loc_forward(ipc_callid_t callid, ipc_call_t *call, void *arg)
[15f3c3f]710{
711 fibril_mutex_lock(&services_list_mutex);
712
713 /*
714 * Get ID from request
715 */
[f9b2cb4c]716 iface_t iface = IPC_GET_ARG1(*call);
[15f3c3f]717 service_id_t id = IPC_GET_ARG2(*call);
718 loc_service_t *svc = loc_service_find_id(id);
719
720 if ((svc == NULL) || (svc->server == NULL) || (!svc->server->sess)) {
721 fibril_mutex_unlock(&services_list_mutex);
722 async_answer_0(callid, ENOENT);
723 return;
724 }
725
726 async_exch_t *exch = async_exchange_begin(svc->server->sess);
[f9b2cb4c]727 async_forward_fast(callid, exch, iface, svc->id, 0, IPC_FF_NONE);
[15f3c3f]728 async_exchange_end(exch);
729
730 fibril_mutex_unlock(&services_list_mutex);
731}
732
733/** Find ID for service identified by name.
734 *
735 * In answer will be send EOK and service ID in arg1 or a error
736 * code from errno.h.
737 *
738 */
739static void loc_service_get_id(ipc_callid_t iid, ipc_call_t *icall)
740{
741 char *fqsn;
742
743 /* Get fqsn */
744 int rc = async_data_write_accept((void **) &fqsn, true, 0,
745 LOC_NAME_MAXLEN, 0, NULL);
746 if (rc != EOK) {
747 async_answer_0(iid, rc);
748 return;
749 }
750
751 char *ns_name;
752 char *name;
753 if (!loc_fqsn_split(fqsn, &ns_name, &name)) {
754 free(fqsn);
755 async_answer_0(iid, EINVAL);
756 return;
757 }
758
759 free(fqsn);
760
761 fibril_mutex_lock(&services_list_mutex);
762 const loc_service_t *svc;
763
764recheck:
765
766 /*
767 * Find service name in the list of known services.
768 */
769 svc = loc_service_find_name(ns_name, name);
770
771 /*
772 * Device was not found.
773 */
774 if (svc == NULL) {
775 if (IPC_GET_ARG1(*icall) & IPC_FLAG_BLOCKING) {
776 /* Blocking lookup */
777 fibril_condvar_wait(&services_list_cv,
778 &services_list_mutex);
779 goto recheck;
780 }
781
782 async_answer_0(iid, ENOENT);
783 free(ns_name);
784 free(name);
785 fibril_mutex_unlock(&services_list_mutex);
786 return;
787 }
788
789 async_answer_1(iid, EOK, svc->id);
790
791 fibril_mutex_unlock(&services_list_mutex);
792 free(ns_name);
793 free(name);
794}
795
796/** Find ID for namespace identified by name.
797 *
798 * In answer will be send EOK and service ID in arg1 or a error
799 * code from errno.h.
800 *
801 */
802static void loc_namespace_get_id(ipc_callid_t iid, ipc_call_t *icall)
803{
804 char *name;
805
806 /* Get service name */
807 int rc = async_data_write_accept((void **) &name, true, 0,
808 LOC_NAME_MAXLEN, 0, NULL);
809 if (rc != EOK) {
810 async_answer_0(iid, rc);
811 return;
812 }
813
814 fibril_mutex_lock(&services_list_mutex);
815 const loc_namespace_t *namespace;
816
817recheck:
818
819 /*
820 * Find namespace name in the list of known namespaces.
821 */
822 namespace = loc_namespace_find_name(name);
823
824 /*
825 * Namespace was not found.
826 */
827 if (namespace == NULL) {
828 if (IPC_GET_ARG1(*icall) & IPC_FLAG_BLOCKING) {
829 /* Blocking lookup */
830 fibril_condvar_wait(&services_list_cv,
831 &services_list_mutex);
832 goto recheck;
833 }
834
835 async_answer_0(iid, ENOENT);
836 free(name);
837 fibril_mutex_unlock(&services_list_mutex);
838 return;
839 }
840
841 async_answer_1(iid, EOK, namespace->id);
842
843 fibril_mutex_unlock(&services_list_mutex);
844 free(name);
845}
846
[77a69ea]847/** Create callback connection.
[12f9f0d0]848 *
[77a69ea]849 * Create callback connection which will be used to send category change
850 * events.
[12f9f0d0]851 *
[77a69ea]852 * On success, answer will contain EOK int retval.
853 * On failure, error code will be sent in retval.
[5cc9eba]854 *
[12f9f0d0]855 */
856static void loc_callback_create(ipc_callid_t iid, ipc_call_t *icall)
857{
[5cc9eba]858 cb_sess_t *cb_sess = calloc(1, sizeof(cb_sess_t));
[12f9f0d0]859 if (cb_sess == NULL) {
860 async_answer_0(iid, ENOMEM);
861 return;
862 }
863
[77a69ea]864 async_sess_t *sess = async_callback_receive(EXCHANGE_SERIALIZE);
865 if (sess == NULL) {
866 free(cb_sess);
867 async_answer_0(iid, ENOMEM);
[12f9f0d0]868 return;
869 }
870
[77a69ea]871 cb_sess->sess = sess;
872 link_initialize(&cb_sess->cb_sess_list);
873
874 fibril_mutex_lock(&callback_sess_mutex);
875 list_append(&cb_sess->cb_sess_list, &callback_sess_list);
[12f9f0d0]876 fibril_mutex_unlock(&callback_sess_mutex);
877
878 async_answer_0(iid, EOK);
879}
880
881void loc_category_change_event(void)
882{
883 fibril_mutex_lock(&callback_sess_mutex);
[77a69ea]884
[feeac0d]885 list_foreach(callback_sess_list, cb_sess_list, cb_sess_t, cb_sess) {
[77a69ea]886 async_exch_t *exch = async_exchange_begin(cb_sess->sess);
[12f9f0d0]887 async_msg_0(exch, LOC_EVENT_CAT_CHANGE);
888 async_exchange_end(exch);
889 }
[77a69ea]890
[12f9f0d0]891 fibril_mutex_unlock(&callback_sess_mutex);
892}
893
[cc574511]894/** Find ID for category specified by name.
895 *
896 * On success, answer will contain EOK int retval and service ID in arg1.
897 * On failure, error code will be sent in retval.
898 *
899 */
900static void loc_category_get_id(ipc_callid_t iid, ipc_call_t *icall)
901{
902 char *name;
903 category_t *cat;
904
905 /* Get service name */
906 int rc = async_data_write_accept((void **) &name, true, 0,
907 LOC_NAME_MAXLEN, 0, NULL);
908 if (rc != EOK) {
909 async_answer_0(iid, rc);
910 return;
911 }
912
913 fibril_mutex_lock(&cdir.mutex);
914
915 cat = category_find_by_name(&cdir, name);
916 if (cat == NULL) {
917 /* Category not found */
918 async_answer_0(iid, ENOENT);
919 goto cleanup;
920 }
921
922 async_answer_1(iid, EOK, cat->id);
923cleanup:
924 fibril_mutex_unlock(&cdir.mutex);
925 free(name);
926}
927
[15f3c3f]928static void loc_id_probe(ipc_callid_t iid, ipc_call_t *icall)
929{
930 fibril_mutex_lock(&services_list_mutex);
931
932 loc_namespace_t *namespace =
933 loc_namespace_find_id(IPC_GET_ARG1(*icall));
934 if (namespace == NULL) {
935 loc_service_t *svc =
936 loc_service_find_id(IPC_GET_ARG1(*icall));
937 if (svc == NULL)
938 async_answer_1(iid, EOK, LOC_OBJECT_NONE);
939 else
940 async_answer_1(iid, EOK, LOC_OBJECT_SERVICE);
941 } else
942 async_answer_1(iid, EOK, LOC_OBJECT_NAMESPACE);
943
944 fibril_mutex_unlock(&services_list_mutex);
945}
946
947static void loc_get_namespace_count(ipc_callid_t iid, ipc_call_t *icall)
948{
949 fibril_mutex_lock(&services_list_mutex);
950 async_answer_1(iid, EOK, list_count(&namespaces_list));
951 fibril_mutex_unlock(&services_list_mutex);
952}
953
954static void loc_get_service_count(ipc_callid_t iid, ipc_call_t *icall)
955{
956 fibril_mutex_lock(&services_list_mutex);
957
958 loc_namespace_t *namespace =
959 loc_namespace_find_id(IPC_GET_ARG1(*icall));
960 if (namespace == NULL)
[8a637a4]961 async_answer_0(iid, EEXIST);
[15f3c3f]962 else
963 async_answer_1(iid, EOK, namespace->refcnt);
964
965 fibril_mutex_unlock(&services_list_mutex);
966}
967
[278ac72]968static void loc_get_categories(ipc_callid_t iid, ipc_call_t *icall)
969{
970 ipc_callid_t callid;
971 size_t size;
972 size_t act_size;
973 int rc;
974
975 if (!async_data_read_receive(&callid, &size)) {
976 async_answer_0(callid, EREFUSED);
977 async_answer_0(iid, EREFUSED);
978 return;
979 }
980
981 category_id_t *id_buf = (category_id_t *) malloc(size);
982 if (id_buf == NULL) {
983 fibril_mutex_unlock(&cdir.mutex);
984 async_answer_0(callid, ENOMEM);
985 async_answer_0(iid, ENOMEM);
986 return;
987 }
988
989 fibril_mutex_lock(&cdir.mutex);
990
991 rc = categ_dir_get_categories(&cdir, id_buf, size, &act_size);
992 if (rc != EOK) {
993 fibril_mutex_unlock(&cdir.mutex);
994 async_answer_0(callid, rc);
995 async_answer_0(iid, rc);
996 return;
997 }
998
999 fibril_mutex_unlock(&cdir.mutex);
1000
1001 sysarg_t retval = async_data_read_finalize(callid, id_buf, size);
1002 free(id_buf);
1003
1004 async_answer_1(iid, retval, act_size);
1005}
1006
[15f3c3f]1007static void loc_get_namespaces(ipc_callid_t iid, ipc_call_t *icall)
1008{
1009 ipc_callid_t callid;
1010 size_t size;
1011 if (!async_data_read_receive(&callid, &size)) {
1012 async_answer_0(callid, EREFUSED);
1013 async_answer_0(iid, EREFUSED);
1014 return;
1015 }
1016
1017 if ((size % sizeof(loc_sdesc_t)) != 0) {
1018 async_answer_0(callid, EINVAL);
1019 async_answer_0(iid, EINVAL);
1020 return;
1021 }
1022
1023 fibril_mutex_lock(&services_list_mutex);
1024
1025 size_t count = size / sizeof(loc_sdesc_t);
1026 if (count != list_count(&namespaces_list)) {
1027 fibril_mutex_unlock(&services_list_mutex);
1028 async_answer_0(callid, EOVERFLOW);
1029 async_answer_0(iid, EOVERFLOW);
1030 return;
1031 }
1032
1033 loc_sdesc_t *desc = (loc_sdesc_t *) malloc(size);
1034 if (desc == NULL) {
1035 fibril_mutex_unlock(&services_list_mutex);
1036 async_answer_0(callid, ENOMEM);
1037 async_answer_0(iid, ENOMEM);
1038 return;
1039 }
1040
1041 size_t pos = 0;
[feeac0d]1042 list_foreach(namespaces_list, namespaces, loc_namespace_t, namespace) {
[15f3c3f]1043 desc[pos].id = namespace->id;
1044 str_cpy(desc[pos].name, LOC_NAME_MAXLEN, namespace->name);
1045 pos++;
1046 }
1047
1048 sysarg_t retval = async_data_read_finalize(callid, desc, size);
1049
1050 free(desc);
1051 fibril_mutex_unlock(&services_list_mutex);
1052
1053 async_answer_0(iid, retval);
1054}
1055
1056static void loc_get_services(ipc_callid_t iid, ipc_call_t *icall)
1057{
1058 /* FIXME: Use faster algorithm which can make better use
1059 of namespaces */
1060
1061 ipc_callid_t callid;
1062 size_t size;
1063 if (!async_data_read_receive(&callid, &size)) {
1064 async_answer_0(callid, EREFUSED);
1065 async_answer_0(iid, EREFUSED);
1066 return;
1067 }
1068
1069 if ((size % sizeof(loc_sdesc_t)) != 0) {
1070 async_answer_0(callid, EINVAL);
1071 async_answer_0(iid, EINVAL);
1072 return;
1073 }
1074
1075 fibril_mutex_lock(&services_list_mutex);
1076
1077 loc_namespace_t *namespace =
1078 loc_namespace_find_id(IPC_GET_ARG1(*icall));
1079 if (namespace == NULL) {
1080 fibril_mutex_unlock(&services_list_mutex);
1081 async_answer_0(callid, ENOENT);
1082 async_answer_0(iid, ENOENT);
1083 return;
1084 }
1085
1086 size_t count = size / sizeof(loc_sdesc_t);
1087 if (count != namespace->refcnt) {
1088 fibril_mutex_unlock(&services_list_mutex);
1089 async_answer_0(callid, EOVERFLOW);
1090 async_answer_0(iid, EOVERFLOW);
1091 return;
1092 }
1093
1094 loc_sdesc_t *desc = (loc_sdesc_t *) malloc(size);
1095 if (desc == NULL) {
1096 fibril_mutex_unlock(&services_list_mutex);
1097 async_answer_0(callid, ENOMEM);
1098 async_answer_0(iid, EREFUSED);
1099 return;
1100 }
1101
1102 size_t pos = 0;
[feeac0d]1103 list_foreach(services_list, services, loc_service_t, service) {
[15f3c3f]1104 if (service->namespace == namespace) {
1105 desc[pos].id = service->id;
1106 str_cpy(desc[pos].name, LOC_NAME_MAXLEN, service->name);
1107 pos++;
1108 }
1109 }
1110
1111 sysarg_t retval = async_data_read_finalize(callid, desc, size);
1112
1113 free(desc);
1114 fibril_mutex_unlock(&services_list_mutex);
1115
1116 async_answer_0(iid, retval);
1117}
1118
[cc574511]1119static void loc_category_get_svcs(ipc_callid_t iid, ipc_call_t *icall)
1120{
1121 ipc_callid_t callid;
1122 size_t size;
1123 size_t act_size;
1124 int rc;
1125
1126 if (!async_data_read_receive(&callid, &size)) {
1127 async_answer_0(callid, EREFUSED);
1128 async_answer_0(iid, EREFUSED);
1129 return;
1130 }
1131
1132 fibril_mutex_lock(&cdir.mutex);
1133
1134 category_t *cat = category_get(&cdir, IPC_GET_ARG1(*icall));
1135 if (cat == NULL) {
1136 fibril_mutex_unlock(&cdir.mutex);
1137 async_answer_0(callid, ENOENT);
1138 async_answer_0(iid, ENOENT);
1139 return;
1140 }
1141
1142 category_id_t *id_buf = (category_id_t *) malloc(size);
1143 if (id_buf == NULL) {
1144 fibril_mutex_unlock(&cdir.mutex);
1145 async_answer_0(callid, ENOMEM);
1146 async_answer_0(iid, ENOMEM);
1147 return;
1148 }
1149
1150 fibril_mutex_lock(&cat->mutex);
1151
1152 rc = category_get_services(cat, id_buf, size, &act_size);
1153 if (rc != EOK) {
1154 fibril_mutex_unlock(&cat->mutex);
1155 fibril_mutex_unlock(&cdir.mutex);
1156 async_answer_0(callid, rc);
1157 async_answer_0(iid, rc);
1158 return;
1159 }
1160
1161 fibril_mutex_unlock(&cat->mutex);
1162 fibril_mutex_unlock(&cdir.mutex);
1163
1164 sysarg_t retval = async_data_read_finalize(callid, id_buf, size);
1165 free(id_buf);
1166
1167 async_answer_1(iid, retval, act_size);
1168}
1169
1170
[15f3c3f]1171static void loc_null_create(ipc_callid_t iid, ipc_call_t *icall)
1172{
1173 fibril_mutex_lock(&null_services_mutex);
1174
1175 unsigned int i;
1176 bool fnd = false;
1177
1178 for (i = 0; i < NULL_SERVICES; i++) {
1179 if (null_services[i] == NULL) {
1180 fnd = true;
1181 break;
1182 }
1183 }
1184
1185 if (!fnd) {
1186 fibril_mutex_unlock(&null_services_mutex);
1187 async_answer_0(iid, ENOMEM);
1188 return;
1189 }
1190
1191 char null[LOC_NAME_MAXLEN];
1192 snprintf(null, LOC_NAME_MAXLEN, "%u", i);
1193
1194 char *dev_name = str_dup(null);
1195 if (dev_name == NULL) {
1196 fibril_mutex_unlock(&null_services_mutex);
1197 async_answer_0(iid, ENOMEM);
1198 return;
1199 }
1200
1201 loc_service_t *service =
1202 (loc_service_t *) malloc(sizeof(loc_service_t));
1203 if (service == NULL) {
1204 fibril_mutex_unlock(&null_services_mutex);
1205 async_answer_0(iid, ENOMEM);
1206 return;
1207 }
1208
1209 fibril_mutex_lock(&services_list_mutex);
1210
1211 loc_namespace_t *namespace = loc_namespace_create("null");
1212 if (namespace == NULL) {
1213 fibril_mutex_lock(&services_list_mutex);
1214 fibril_mutex_unlock(&null_services_mutex);
1215 async_answer_0(iid, ENOMEM);
1216 return;
1217 }
1218
1219 link_initialize(&service->services);
1220 link_initialize(&service->server_services);
[03f4acf]1221 list_initialize(&service->cat_memb);
[15f3c3f]1222
1223 /* Get unique service ID */
1224 service->id = loc_create_id();
1225 service->server = NULL;
1226
1227 loc_namespace_addref(namespace, service);
1228 service->name = dev_name;
1229
1230 /*
1231 * Insert service into list of all services and into null services array.
1232 * Insert service into a dummy list of null server's services so that it
1233 * can be safely removed later.
1234 */
1235 list_append(&service->services, &services_list);
1236 list_append(&service->server_services, &dummy_null_services);
1237 null_services[i] = service;
1238
1239 fibril_mutex_unlock(&services_list_mutex);
1240 fibril_mutex_unlock(&null_services_mutex);
1241
1242 async_answer_1(iid, EOK, (sysarg_t) i);
1243}
1244
1245static void loc_null_destroy(ipc_callid_t iid, ipc_call_t *icall)
1246{
1247 sysarg_t i = IPC_GET_ARG1(*icall);
1248 if (i >= NULL_SERVICES) {
1249 async_answer_0(iid, ELIMIT);
1250 return;
1251 }
1252
1253 fibril_mutex_lock(&null_services_mutex);
1254
1255 if (null_services[i] == NULL) {
1256 fibril_mutex_unlock(&null_services_mutex);
1257 async_answer_0(iid, ENOENT);
1258 return;
1259 }
1260
1261 fibril_mutex_lock(&services_list_mutex);
[d0dd7b5]1262 fibril_mutex_lock(&cdir.mutex);
[15f3c3f]1263 loc_service_unregister_core(null_services[i]);
[d0dd7b5]1264 fibril_mutex_unlock(&cdir.mutex);
[15f3c3f]1265 fibril_mutex_unlock(&services_list_mutex);
1266
1267 null_services[i] = NULL;
1268
1269 fibril_mutex_unlock(&null_services_mutex);
1270 async_answer_0(iid, EOK);
1271}
1272
[cc574511]1273static void loc_service_add_to_cat(ipc_callid_t iid, ipc_call_t *icall)
1274{
1275 category_t *cat;
1276 loc_service_t *svc;
1277 catid_t cat_id;
1278 service_id_t svc_id;
1279 sysarg_t retval;
1280
1281 svc_id = IPC_GET_ARG1(*icall);
1282 cat_id = IPC_GET_ARG2(*icall);
1283
1284 fibril_mutex_lock(&services_list_mutex);
1285 fibril_mutex_lock(&cdir.mutex);
1286
1287 cat = category_get(&cdir, cat_id);
1288 svc = loc_service_find_id(svc_id);
1289
[aff587f]1290 if (cat == NULL || svc == NULL) {
1291 fibril_mutex_unlock(&cdir.mutex);
1292 fibril_mutex_unlock(&services_list_mutex);
1293 async_answer_0(iid, ENOENT);
1294 return;
1295 }
1296
[cc574511]1297 fibril_mutex_lock(&cat->mutex);
1298 retval = category_add_service(cat, svc);
1299
1300 fibril_mutex_unlock(&cat->mutex);
1301 fibril_mutex_unlock(&cdir.mutex);
1302 fibril_mutex_unlock(&services_list_mutex);
1303
[adb1ae9]1304 /*
1305 * First send out all notifications and only then answer the request.
1306 * Otherwise the current fibril might block and transitively wait for
1307 * the completion of requests that are routed to it via an IPC loop.
1308 */
[12f9f0d0]1309 loc_category_change_event();
[adb1ae9]1310 async_answer_0(iid, retval);
[cc574511]1311}
1312
1313
[15f3c3f]1314/** Initialize location service.
1315 *
1316 *
1317 */
1318static bool loc_init(void)
1319{
1320 unsigned int i;
[cc574511]1321 category_t *cat;
1322
[15f3c3f]1323 for (i = 0; i < NULL_SERVICES; i++)
1324 null_services[i] = NULL;
1325
[cc574511]1326 categ_dir_init(&cdir);
1327
[e96047c]1328 cat = category_new("disk");
1329 categ_dir_add_cat(&cdir, cat);
1330
[372df8f]1331 cat = category_new("partition");
1332 categ_dir_add_cat(&cdir, cat);
1333
[e2e56e67]1334 cat = category_new("iplink");
1335 categ_dir_add_cat(&cdir, cat);
1336
[cc574511]1337 cat = category_new("keyboard");
1338 categ_dir_add_cat(&cdir, cat);
1339
1340 cat = category_new("mouse");
1341 categ_dir_add_cat(&cdir, cat);
1342
[1e94e09]1343 cat = category_new("led");
1344 categ_dir_add_cat(&cdir, cat);
1345
[cc574511]1346 cat = category_new("serial");
1347 categ_dir_add_cat(&cdir, cat);
1348
[557b7b3]1349 cat = category_new("clock");
1350 categ_dir_add_cat(&cdir, cat);
1351
[a9abe5fc]1352 cat = category_new("test3");
1353 categ_dir_add_cat(&cdir, cat);
1354
[e280857]1355 cat = category_new("usbhc");
1356 categ_dir_add_cat(&cdir, cat);
1357
[a9abe5fc]1358 cat = category_new("virt-null");
1359 categ_dir_add_cat(&cdir, cat);
1360
[d0dd7b5]1361 cat = category_new("virtual");
1362 categ_dir_add_cat(&cdir, cat);
[609243f4]1363
1364 cat = category_new("nic");
1365 categ_dir_add_cat(&cdir, cat);
[864762a]1366
1367 cat = category_new("ieee80211");
1368 categ_dir_add_cat(&cdir, cat);
[6d5e378]1369
[9a2eb14]1370 cat = category_new("irc");
1371 categ_dir_add_cat(&cdir, cat);
1372
[6d5e378]1373 cat = category_new("visualizer");
1374 categ_dir_add_cat(&cdir, cat);
1375
1376 cat = category_new("renderer");
1377 categ_dir_add_cat(&cdir, cat);
[609243f4]1378
[94694a4]1379 cat = category_new("audio-pcm");
1380 categ_dir_add_cat(&cdir, cat);
1381
[15f3c3f]1382 return true;
1383}
1384
1385/** Handle connection on supplier port.
1386 *
1387 */
[f9b2cb4c]1388static void loc_connection_supplier(ipc_callid_t iid, ipc_call_t *icall, void *arg)
[15f3c3f]1389{
1390 /* Accept connection */
1391 async_answer_0(iid, EOK);
1392
1393 loc_server_t *server = loc_server_register();
1394 if (server == NULL)
1395 return;
1396
1397 while (true) {
1398 ipc_call_t call;
1399 ipc_callid_t callid = async_get_call(&call);
1400
1401 if (!IPC_GET_IMETHOD(call))
1402 break;
1403
1404 switch (IPC_GET_IMETHOD(call)) {
1405 case LOC_SERVER_UNREGISTER:
1406 if (server == NULL)
1407 async_answer_0(callid, ENOENT);
1408 else
1409 async_answer_0(callid, EOK);
1410 break;
[cc574511]1411 case LOC_SERVICE_ADD_TO_CAT:
1412 /* Add service to category */
1413 loc_service_add_to_cat(callid, &call);
1414 break;
[15f3c3f]1415 case LOC_SERVICE_REGISTER:
1416 /* Register one service */
1417 loc_service_register(callid, &call, server);
1418 break;
1419 case LOC_SERVICE_UNREGISTER:
1420 /* Remove one service */
1421 loc_service_unregister(callid, &call, server);
1422 break;
1423 case LOC_SERVICE_GET_ID:
1424 loc_service_get_id(callid, &call);
1425 break;
1426 case LOC_NAMESPACE_GET_ID:
1427 loc_namespace_get_id(callid, &call);
1428 break;
1429 default:
1430 async_answer_0(callid, ENOENT);
1431 }
1432 }
1433
1434 if (server != NULL) {
1435 /*
1436 * Unregister the server and all its services.
1437 */
1438 loc_server_unregister(server);
1439 server = NULL;
1440 }
1441}
1442
1443/** Handle connection on consumer port.
1444 *
1445 */
[f9b2cb4c]1446static void loc_connection_consumer(ipc_callid_t iid, ipc_call_t *icall, void *arg)
[15f3c3f]1447{
1448 /* Accept connection */
1449 async_answer_0(iid, EOK);
1450
1451 while (true) {
1452 ipc_call_t call;
1453 ipc_callid_t callid = async_get_call(&call);
1454
1455 if (!IPC_GET_IMETHOD(call))
1456 break;
1457
1458 switch (IPC_GET_IMETHOD(call)) {
1459 case LOC_SERVICE_GET_ID:
1460 loc_service_get_id(callid, &call);
1461 break;
[cce8a83]1462 case LOC_SERVICE_GET_NAME:
1463 loc_service_get_name(callid, &call);
1464 break;
[a3fcfba]1465 case LOC_SERVICE_GET_SERVER_NAME:
1466 loc_service_get_server_name(callid, &call);
1467 break;
[15f3c3f]1468 case LOC_NAMESPACE_GET_ID:
1469 loc_namespace_get_id(callid, &call);
1470 break;
[12f9f0d0]1471 case LOC_CALLBACK_CREATE:
1472 loc_callback_create(callid, &call);
1473 break;
[cc574511]1474 case LOC_CATEGORY_GET_ID:
1475 loc_category_get_id(callid, &call);
1476 break;
[763e0cd]1477 case LOC_CATEGORY_GET_NAME:
1478 loc_category_get_name(callid, &call);
1479 break;
[cc574511]1480 case LOC_CATEGORY_GET_SVCS:
1481 loc_category_get_svcs(callid, &call);
1482 break;
[15f3c3f]1483 case LOC_ID_PROBE:
1484 loc_id_probe(callid, &call);
1485 break;
1486 case LOC_NULL_CREATE:
1487 loc_null_create(callid, &call);
1488 break;
1489 case LOC_NULL_DESTROY:
1490 loc_null_destroy(callid, &call);
1491 break;
1492 case LOC_GET_NAMESPACE_COUNT:
1493 loc_get_namespace_count(callid, &call);
1494 break;
1495 case LOC_GET_SERVICE_COUNT:
1496 loc_get_service_count(callid, &call);
1497 break;
[278ac72]1498 case LOC_GET_CATEGORIES:
1499 loc_get_categories(callid, &call);
1500 break;
[15f3c3f]1501 case LOC_GET_NAMESPACES:
1502 loc_get_namespaces(callid, &call);
1503 break;
1504 case LOC_GET_SERVICES:
1505 loc_get_services(callid, &call);
1506 break;
1507 default:
1508 async_answer_0(callid, ENOENT);
1509 }
1510 }
1511}
1512
1513/**
1514 *
1515 */
1516int main(int argc, char *argv[])
1517{
1518 printf("%s: HelenOS Location Service\n", NAME);
1519
1520 if (!loc_init()) {
1521 printf("%s: Error while initializing service\n", NAME);
1522 return -1;
1523 }
1524
[f9b2cb4c]1525 port_id_t port;
1526 int rc = async_create_port(INTERFACE_LOC_SUPPLIER,
1527 loc_connection_supplier, NULL, &port);
1528 if (rc != EOK)
1529 return rc;
1530
1531 rc = async_create_port(INTERFACE_LOC_CONSUMER,
1532 loc_connection_consumer, NULL, &port);
1533 if (rc != EOK)
1534 return rc;
1535
[15f3c3f]1536 /* Set a handler of incomming connections */
[f9b2cb4c]1537 async_set_fallback_port_handler(loc_forward, NULL);
[15f3c3f]1538
1539 /* Register location service at naming service */
[f9b2cb4c]1540 rc = service_register(SERVICE_LOC);
[50ad3f3]1541 if (rc != EOK)
1542 return rc;
[15f3c3f]1543
1544 printf("%s: Accepting connections\n", NAME);
1545 async_manager();
1546
1547 /* Never reached */
1548 return 0;
1549}
1550
1551/**
1552 * @}
1553 */
Note: See TracBrowser for help on using the repository browser.