source: mainline/uspace/srv/locsrv/locsrv.c@ 39b54fe

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 39b54fe was 25a179e, checked in by Jiří Zárevúcky <zarevucky.jiri@…>, 8 years ago

IPC return values are always errno constants. Adjust types to reflect that.

In principle, IPC server is not allowed to return non-errno values via
the "main" return value, because kernel interprets it (e.g. EHANGUP).
It's still possible to return arbitrary additional return values alongside EOK,
which are not interpreted in normal communication.

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