source: mainline/uspace/srv/locsrv/locsrv.c@ 4224ef7

Last change on this file since 4224ef7 was 4224ef7, checked in by Matthieu Riolo <matthieu.riolo@…>, 6 years ago

sysman: Add VFS FS server autostart

  • VFS autostart instrumentation removes explicit dependency on FS servers.
  • Compositor service properly named, it's now resolved as implicit dependency.

Conflicts:

boot/Makefile.common
uspace/lib/gui/window.c
uspace/srv/locsrv/locsrv.c
uspace/srv/vfs/vfs.c
uspace/srv/vfs/vfs_ops.c

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