source: mainline/uspace/srv/ns/service.c@ edc64c0

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since edc64c0 was 984a9ba, checked in by Martin Decky <martin@…>, 7 years ago

do not expose the call capability handler from the async framework

Keep the call capability handler encapsulated within the async framework
and do not expose it explicitly via its API. Use the pointer to
ipc_call_t as the sole object identifying an IPC call in the code that
uses the async framework.

This plugs a major leak in the abstraction and also simplifies both the
async framework (slightly) and all IPC servers.

  • Property mode set to 100644
File size: 5.6 KB
Line 
1/*
2 * Copyright (c) 2009 Martin Decky
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29/** @addtogroup ns
30 * @{
31 */
32
33#include <adt/hash_table.h>
34#include <assert.h>
35#include <async.h>
36#include <errno.h>
37#include <stdio.h>
38#include <stdlib.h>
39#include "service.h"
40#include "ns.h"
41
42/** Service hash table item. */
43typedef struct {
44 ht_link_t link;
45
46 /** Service ID */
47 service_t service;
48
49 /** Session to the service */
50 async_sess_t *sess;
51} hashed_service_t;
52
53static size_t service_key_hash(void *key)
54{
55 return *(service_t *) key;
56}
57
58static size_t service_hash(const ht_link_t *item)
59{
60 hashed_service_t *service =
61 hash_table_get_inst(item, hashed_service_t, link);
62
63 return service->service;
64}
65
66static bool service_key_equal(void *key, const ht_link_t *item)
67{
68 hashed_service_t *service =
69 hash_table_get_inst(item, hashed_service_t, link);
70
71 return service->service == *(service_t *) key;
72}
73
74/** Operations for service hash table. */
75static hash_table_ops_t service_hash_table_ops = {
76 .hash = service_hash,
77 .key_hash = service_key_hash,
78 .key_equal = service_key_equal,
79 .equal = NULL,
80 .remove_callback = NULL
81};
82
83/** Service hash table structure. */
84static hash_table_t service_hash_table;
85
86/** Pending connection structure. */
87typedef struct {
88 link_t link;
89 service_t service; /**< Service ID */
90 iface_t iface; /**< Interface ID */
91 ipc_call_t call; /**< Call waiting for the connection */
92} pending_conn_t;
93
94static list_t pending_conn;
95
96errno_t service_init(void)
97{
98 if (!hash_table_create(&service_hash_table, 0, 0,
99 &service_hash_table_ops)) {
100 printf("%s: No memory available for services\n", NAME);
101 return ENOMEM;
102 }
103
104 list_initialize(&pending_conn);
105
106 return EOK;
107}
108
109/** Process pending connection requests */
110void process_pending_conn(void)
111{
112loop:
113 list_foreach(pending_conn, link, pending_conn_t, pending) {
114 ht_link_t *link = hash_table_find(&service_hash_table, &pending->service);
115 if (!link)
116 continue;
117
118 hashed_service_t *hashed_service = hash_table_get_inst(link, hashed_service_t, link);
119 async_exch_t *exch = async_exchange_begin(hashed_service->sess);
120 async_forward_fast(&pending->call, exch, pending->iface,
121 IPC_GET_ARG3(pending->call), 0, IPC_FF_NONE);
122 async_exchange_end(exch);
123
124 list_remove(&pending->link);
125 free(pending);
126
127 goto loop;
128 }
129}
130
131/** Register service.
132 *
133 * @param service Service to be registered.
134 * @param phone Phone to be used for connections to the service.
135 * @param call Pointer to call structure.
136 *
137 * @return Zero on success or a value from @ref errno.h.
138 *
139 */
140errno_t register_service(service_t service, sysarg_t phone, ipc_call_t *call)
141{
142 if (hash_table_find(&service_hash_table, &service))
143 return EEXIST;
144
145 hashed_service_t *hashed_service =
146 (hashed_service_t *) malloc(sizeof(hashed_service_t));
147 if (!hashed_service)
148 return ENOMEM;
149
150 hashed_service->service = service;
151 hashed_service->sess = async_callback_receive(EXCHANGE_SERIALIZE);
152 if (hashed_service->sess == NULL)
153 return EIO;
154
155 hash_table_insert(&service_hash_table, &hashed_service->link);
156 return EOK;
157}
158
159/** Connect client to service.
160 *
161 * @param service Service to be connected to.
162 * @param iface Interface to be connected to.
163 * @param call Pointer to call structure.
164 *
165 * @return Zero on success or a value from @ref errno.h.
166 *
167 */
168void connect_to_service(service_t service, iface_t iface, ipc_call_t *call)
169{
170 sysarg_t flags = IPC_GET_ARG4(*call);
171 errno_t retval;
172
173 ht_link_t *link = hash_table_find(&service_hash_table, &service);
174 if (!link) {
175 if (flags & IPC_FLAG_BLOCKING) {
176 /* Blocking connection, add to pending list */
177 pending_conn_t *pending =
178 (pending_conn_t *) malloc(sizeof(pending_conn_t));
179 if (!pending) {
180 retval = ENOMEM;
181 goto out;
182 }
183
184 link_initialize(&pending->link);
185 pending->service = service;
186 pending->iface = iface;
187 pending->call = *call;
188
189 list_append(&pending->link, &pending_conn);
190 return;
191 }
192
193 retval = ENOENT;
194 goto out;
195 }
196
197 hashed_service_t *hashed_service = hash_table_get_inst(link, hashed_service_t, link);
198 async_exch_t *exch = async_exchange_begin(hashed_service->sess);
199 async_forward_fast(call, exch, iface, IPC_GET_ARG3(*call), 0, IPC_FF_NONE);
200 async_exchange_end(exch);
201 return;
202
203out:
204 async_answer_0(call, retval);
205}
206
207/**
208 * @}
209 */
Note: See TracBrowser for help on using the repository browser.