source: mainline/uspace/lib/c/generic/iplink_srv.c@ 05882233

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 05882233 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: 7.8 KB
Line 
1/*
2 * Copyright (c) 2012 Jiri Svoboda
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 libc
30 * @{
31 */
32/**
33 * @file
34 * @brief IP link server stub
35 */
36
37#include <errno.h>
38#include <ipc/iplink.h>
39#include <stdlib.h>
40#include <stddef.h>
41#include <inet/addr.h>
42#include <inet/iplink_srv.h>
43
44static void iplink_get_mtu_srv(iplink_srv_t *srv, ipc_call_t *call)
45{
46 size_t mtu;
47 errno_t rc = srv->ops->get_mtu(srv, &mtu);
48 async_answer_1(call, rc, mtu);
49}
50
51static void iplink_get_mac48_srv(iplink_srv_t *srv, ipc_call_t *icall)
52{
53 addr48_t mac;
54 errno_t rc = srv->ops->get_mac48(srv, &mac);
55 if (rc != EOK) {
56 async_answer_0(icall, rc);
57 return;
58 }
59
60 ipc_call_t call;
61 size_t size;
62 if (!async_data_read_receive(&call, &size)) {
63 async_answer_0(&call, EREFUSED);
64 async_answer_0(icall, EREFUSED);
65 return;
66 }
67
68 if (size != sizeof(addr48_t)) {
69 async_answer_0(&call, EINVAL);
70 async_answer_0(icall, EINVAL);
71 return;
72 }
73
74 rc = async_data_read_finalize(&call, &mac, size);
75 if (rc != EOK)
76 async_answer_0(&call, rc);
77
78 async_answer_0(icall, rc);
79}
80
81static void iplink_set_mac48_srv(iplink_srv_t *srv, ipc_call_t *icall)
82{
83 errno_t rc;
84 size_t size;
85 addr48_t mac;
86
87 ipc_call_t call;
88 if (!async_data_write_receive(&call, &size)) {
89 async_answer_0(&call, EREFUSED);
90 async_answer_0(icall, EREFUSED);
91 }
92
93 rc = srv->ops->set_mac48(srv, &mac);
94 if (rc != EOK) {
95 async_answer_0(icall, rc);
96 return;
97 }
98
99 rc = async_data_read_finalize(&call, &mac, sizeof(addr48_t));
100 if (rc != EOK)
101 async_answer_0(&call, rc);
102
103 async_answer_0(icall, rc);
104}
105
106static void iplink_addr_add_srv(iplink_srv_t *srv, ipc_call_t *icall)
107{
108 ipc_call_t call;
109 size_t size;
110 if (!async_data_write_receive(&call, &size)) {
111 async_answer_0(&call, EREFUSED);
112 async_answer_0(icall, EREFUSED);
113 return;
114 }
115
116 if (size != sizeof(inet_addr_t)) {
117 async_answer_0(&call, EINVAL);
118 async_answer_0(icall, EINVAL);
119 return;
120 }
121
122 inet_addr_t addr;
123 errno_t rc = async_data_write_finalize(&call, &addr, size);
124 if (rc != EOK) {
125 async_answer_0(&call, rc);
126 async_answer_0(icall, rc);
127 }
128
129 rc = srv->ops->addr_add(srv, &addr);
130 async_answer_0(icall, rc);
131}
132
133static void iplink_addr_remove_srv(iplink_srv_t *srv, ipc_call_t *icall)
134{
135 ipc_call_t call;
136 size_t size;
137 if (!async_data_write_receive(&call, &size)) {
138 async_answer_0(&call, EREFUSED);
139 async_answer_0(icall, EREFUSED);
140 return;
141 }
142
143 if (size != sizeof(inet_addr_t)) {
144 async_answer_0(&call, EINVAL);
145 async_answer_0(icall, EINVAL);
146 return;
147 }
148
149 inet_addr_t addr;
150 errno_t rc = async_data_write_finalize(&call, &addr, size);
151 if (rc != EOK) {
152 async_answer_0(&call, rc);
153 async_answer_0(icall, rc);
154 }
155
156 rc = srv->ops->addr_remove(srv, &addr);
157 async_answer_0(icall, rc);
158}
159
160static void iplink_send_srv(iplink_srv_t *srv, ipc_call_t *icall)
161{
162 iplink_sdu_t sdu;
163
164 sdu.src = IPC_GET_ARG1(*icall);
165 sdu.dest = IPC_GET_ARG2(*icall);
166
167 errno_t rc = async_data_write_accept(&sdu.data, false, 0, 0, 0,
168 &sdu.size);
169 if (rc != EOK) {
170 async_answer_0(icall, rc);
171 return;
172 }
173
174 rc = srv->ops->send(srv, &sdu);
175 free(sdu.data);
176 async_answer_0(icall, rc);
177}
178
179static void iplink_send6_srv(iplink_srv_t *srv, ipc_call_t *icall)
180{
181 iplink_sdu6_t sdu;
182
183 ipc_call_t call;
184 size_t size;
185 if (!async_data_write_receive(&call, &size)) {
186 async_answer_0(&call, EREFUSED);
187 async_answer_0(icall, EREFUSED);
188 return;
189 }
190
191 if (size != sizeof(addr48_t)) {
192 async_answer_0(&call, EINVAL);
193 async_answer_0(icall, EINVAL);
194 return;
195 }
196
197 errno_t rc = async_data_write_finalize(&call, &sdu.dest, size);
198 if (rc != EOK) {
199 async_answer_0(&call, rc);
200 async_answer_0(icall, rc);
201 }
202
203 rc = async_data_write_accept(&sdu.data, false, 0, 0, 0,
204 &sdu.size);
205 if (rc != EOK) {
206 async_answer_0(icall, rc);
207 return;
208 }
209
210 rc = srv->ops->send6(srv, &sdu);
211 free(sdu.data);
212 async_answer_0(icall, rc);
213}
214
215void iplink_srv_init(iplink_srv_t *srv)
216{
217 fibril_mutex_initialize(&srv->lock);
218 srv->connected = false;
219 srv->ops = NULL;
220 srv->arg = NULL;
221 srv->client_sess = NULL;
222}
223
224errno_t iplink_conn(ipc_call_t *icall, void *arg)
225{
226 iplink_srv_t *srv = (iplink_srv_t *) arg;
227 errno_t rc;
228
229 fibril_mutex_lock(&srv->lock);
230 if (srv->connected) {
231 fibril_mutex_unlock(&srv->lock);
232 async_answer_0(icall, EBUSY);
233 return EBUSY;
234 }
235
236 srv->connected = true;
237 fibril_mutex_unlock(&srv->lock);
238
239 /* Accept the connection */
240 async_answer_0(icall, EOK);
241
242 async_sess_t *sess = async_callback_receive(EXCHANGE_SERIALIZE);
243 if (sess == NULL)
244 return ENOMEM;
245
246 srv->client_sess = sess;
247
248 rc = srv->ops->open(srv);
249 if (rc != EOK)
250 return rc;
251
252 while (true) {
253 ipc_call_t call;
254 async_get_call(&call);
255 sysarg_t method = IPC_GET_IMETHOD(call);
256
257 if (!method) {
258 /* The other side has hung up */
259 fibril_mutex_lock(&srv->lock);
260 srv->connected = false;
261 fibril_mutex_unlock(&srv->lock);
262 async_answer_0(&call, EOK);
263 break;
264 }
265
266 switch (method) {
267 case IPLINK_GET_MTU:
268 iplink_get_mtu_srv(srv, &call);
269 break;
270 case IPLINK_GET_MAC48:
271 iplink_get_mac48_srv(srv, &call);
272 break;
273 case IPLINK_SET_MAC48:
274 iplink_set_mac48_srv(srv, &call);
275 break;
276 case IPLINK_SEND:
277 iplink_send_srv(srv, &call);
278 break;
279 case IPLINK_SEND6:
280 iplink_send6_srv(srv, &call);
281 break;
282 case IPLINK_ADDR_ADD:
283 iplink_addr_add_srv(srv, &call);
284 break;
285 case IPLINK_ADDR_REMOVE:
286 iplink_addr_remove_srv(srv, &call);
287 break;
288 default:
289 async_answer_0(&call, EINVAL);
290 }
291 }
292
293 return srv->ops->close(srv);
294}
295
296/* XXX Version should be part of @a sdu */
297errno_t iplink_ev_recv(iplink_srv_t *srv, iplink_recv_sdu_t *sdu, ip_ver_t ver)
298{
299 if (srv->client_sess == NULL)
300 return EIO;
301
302 async_exch_t *exch = async_exchange_begin(srv->client_sess);
303
304 ipc_call_t answer;
305 aid_t req = async_send_1(exch, IPLINK_EV_RECV, (sysarg_t)ver,
306 &answer);
307
308 errno_t rc = async_data_write_start(exch, sdu->data, sdu->size);
309 async_exchange_end(exch);
310
311 if (rc != EOK) {
312 async_forget(req);
313 return rc;
314 }
315
316 errno_t retval;
317 async_wait_for(req, &retval);
318 if (retval != EOK)
319 return retval;
320
321 return EOK;
322}
323
324errno_t iplink_ev_change_addr(iplink_srv_t *srv, addr48_t *addr)
325{
326 if (srv->client_sess == NULL)
327 return EIO;
328
329 async_exch_t *exch = async_exchange_begin(srv->client_sess);
330
331 ipc_call_t answer;
332 aid_t req = async_send_0(exch, IPLINK_EV_CHANGE_ADDR, &answer);
333
334 errno_t rc = async_data_write_start(exch, addr, sizeof(addr48_t));
335 async_exchange_end(exch);
336
337 if (rc != EOK) {
338 async_forget(req);
339 return rc;
340 }
341
342 errno_t retval;
343 async_wait_for(req, &retval);
344 if (retval != EOK)
345 return retval;
346
347 return EOK;
348}
349
350/** @}
351 */
Note: See TracBrowser for help on using the repository browser.