source: mainline/uspace/srv/locsrv/locsrv.c@ 8dab988

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 8dab988 was 7c3fb9b, checked in by Jiri Svoboda <jiri@…>, 7 years ago

Fix block comment formatting (ccheck).

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