source: mainline/uspace/lib/c/generic/iplink.c@ 5c38838

Last change on this file since 5c38838 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: 6.6 KB
RevLine 
[f834f90d]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 client stub
35 */
36
37#include <async.h>
38#include <assert.h>
39#include <errno.h>
40#include <inet/iplink.h>
[a2e3ee6]41#include <inet/addr.h>
[f834f90d]42#include <ipc/iplink.h>
43#include <ipc/services.h>
44#include <loc.h>
45#include <stdlib.h>
46
[984a9ba]47static void iplink_cb_conn(ipc_call_t *icall, void *arg);
[f834f90d]48
[b7fd2a0]49errno_t iplink_open(async_sess_t *sess, iplink_ev_ops_t *ev_ops, void *arg,
[f834f90d]50 iplink_t **riplink)
51{
[77ad86c]52 iplink_t *iplink = calloc(1, sizeof(iplink_t));
[f834f90d]53 if (iplink == NULL)
54 return ENOMEM;
[a35b458]55
[f834f90d]56 iplink->sess = sess;
57 iplink->ev_ops = ev_ops;
[8d48c7e]58 iplink->arg = arg;
[a35b458]59
[f834f90d]60 async_exch_t *exch = async_exchange_begin(sess);
[f9b2cb4c]61
62 port_id_t port;
[b7fd2a0]63 errno_t rc = async_create_callback_port(exch, INTERFACE_IPLINK_CB, 0, 0,
[f9b2cb4c]64 iplink_cb_conn, iplink, &port);
[a35b458]65
[f834f90d]66 async_exchange_end(exch);
[a35b458]67
[f834f90d]68 if (rc != EOK)
69 goto error;
[a35b458]70
[f834f90d]71 *riplink = iplink;
72 return EOK;
[a35b458]73
[f834f90d]74error:
75 if (iplink != NULL)
76 free(iplink);
[a35b458]77
[f834f90d]78 return rc;
79}
80
81void iplink_close(iplink_t *iplink)
82{
83 /* XXX Synchronize with iplink_cb_conn */
84 free(iplink);
85}
86
[b7fd2a0]87errno_t iplink_send(iplink_t *iplink, iplink_sdu_t *sdu)
[f834f90d]88{
89 async_exch_t *exch = async_exchange_begin(iplink->sess);
[a35b458]90
[f834f90d]91 ipc_call_t answer;
[a17356fd]92 aid_t req = async_send_2(exch, IPLINK_SEND, (sysarg_t) sdu->src,
93 (sysarg_t) sdu->dest, &answer);
[a35b458]94
[b7fd2a0]95 errno_t rc = async_data_write_start(exch, sdu->data, sdu->size);
[a35b458]96
[a17356fd]97 async_exchange_end(exch);
[a35b458]98
[02a09ed]99 if (rc != EOK) {
100 async_forget(req);
101 return rc;
102 }
[a35b458]103
[b7fd2a0]104 errno_t retval;
[a17356fd]105 async_wait_for(req, &retval);
[a35b458]106
[25a179e]107 return retval;
[a17356fd]108}
109
[b7fd2a0]110errno_t iplink_send6(iplink_t *iplink, iplink_sdu6_t *sdu)
[a17356fd]111{
112 async_exch_t *exch = async_exchange_begin(iplink->sess);
[a35b458]113
[a17356fd]114 ipc_call_t answer;
115 aid_t req = async_send_0(exch, IPLINK_SEND6, &answer);
[a35b458]116
[b7fd2a0]117 errno_t rc = async_data_write_start(exch, &sdu->dest, sizeof(addr48_t));
[02a09ed]118 if (rc != EOK) {
119 async_exchange_end(exch);
120 async_forget(req);
121 return rc;
122 }
[a35b458]123
[02a09ed]124 rc = async_data_write_start(exch, sdu->data, sdu->size);
[a35b458]125
[f834f90d]126 async_exchange_end(exch);
[a35b458]127
[f834f90d]128 if (rc != EOK) {
[50b581d]129 async_forget(req);
[f834f90d]130 return rc;
131 }
[a35b458]132
[b7fd2a0]133 errno_t retval;
[f834f90d]134 async_wait_for(req, &retval);
[a35b458]135
[25a179e]136 return retval;
[f834f90d]137}
138
[b7fd2a0]139errno_t iplink_get_mtu(iplink_t *iplink, size_t *rmtu)
[f834f90d]140{
141 async_exch_t *exch = async_exchange_begin(iplink->sess);
[a35b458]142
[a17356fd]143 sysarg_t mtu;
[b7fd2a0]144 errno_t rc = async_req_0_1(exch, IPLINK_GET_MTU, &mtu);
[a35b458]145
[f834f90d]146 async_exchange_end(exch);
[a35b458]147
[f834f90d]148 if (rc != EOK)
149 return rc;
[a35b458]150
[f834f90d]151 *rmtu = mtu;
152 return EOK;
153}
154
[b7fd2a0]155errno_t iplink_get_mac48(iplink_t *iplink, addr48_t *mac)
[a17356fd]156{
157 async_exch_t *exch = async_exchange_begin(iplink->sess);
[a35b458]158
[a17356fd]159 ipc_call_t answer;
160 aid_t req = async_send_0(exch, IPLINK_GET_MAC48, &answer);
[a35b458]161
[b7fd2a0]162 errno_t rc = async_data_read_start(exch, mac, sizeof(addr48_t));
[a35b458]163
[a17356fd]164 loc_exchange_end(exch);
[a35b458]165
[a17356fd]166 if (rc != EOK) {
167 async_forget(req);
168 return rc;
169 }
[a35b458]170
[b7fd2a0]171 errno_t retval;
[a17356fd]172 async_wait_for(req, &retval);
[a35b458]173
[25a179e]174 return retval;
[a17356fd]175}
176
[b7fd2a0]177errno_t iplink_set_mac48(iplink_t *iplink, addr48_t mac)
[c3b25985]178{
179 async_exch_t *exch = async_exchange_begin(iplink->sess);
[a35b458]180
[c3b25985]181 ipc_call_t answer;
182 aid_t req = async_send_0(exch, IPLINK_GET_MAC48, &answer);
[a35b458]183
[b7fd2a0]184 errno_t rc = async_data_read_start(exch, mac, sizeof(addr48_t));
[a35b458]185
[c3b25985]186 loc_exchange_end(exch);
[a35b458]187
[c3b25985]188 if (rc != EOK) {
189 async_forget(req);
190 return rc;
191 }
[a35b458]192
[b7fd2a0]193 errno_t retval;
[c3b25985]194 async_wait_for(req, &retval);
[a35b458]195
[25a179e]196 return retval;
[c3b25985]197}
198
[b7fd2a0]199errno_t iplink_addr_add(iplink_t *iplink, inet_addr_t *addr)
[962f03b]200{
201 async_exch_t *exch = async_exchange_begin(iplink->sess);
[a35b458]202
[02a09ed]203 ipc_call_t answer;
204 aid_t req = async_send_0(exch, IPLINK_ADDR_ADD, &answer);
[a35b458]205
[b7fd2a0]206 errno_t rc = async_data_write_start(exch, addr, sizeof(inet_addr_t));
[962f03b]207 async_exchange_end(exch);
[a35b458]208
[02a09ed]209 if (rc != EOK) {
210 async_forget(req);
211 return rc;
212 }
[a35b458]213
[b7fd2a0]214 errno_t retval;
[02a09ed]215 async_wait_for(req, &retval);
[a35b458]216
[25a179e]217 return retval;
[962f03b]218}
219
[b7fd2a0]220errno_t iplink_addr_remove(iplink_t *iplink, inet_addr_t *addr)
[962f03b]221{
222 async_exch_t *exch = async_exchange_begin(iplink->sess);
[a35b458]223
[02a09ed]224 ipc_call_t answer;
225 aid_t req = async_send_0(exch, IPLINK_ADDR_REMOVE, &answer);
[a35b458]226
[b7fd2a0]227 errno_t rc = async_data_write_start(exch, addr, sizeof(inet_addr_t));
[962f03b]228 async_exchange_end(exch);
[a35b458]229
[02a09ed]230 if (rc != EOK) {
231 async_forget(req);
232 return rc;
233 }
[a35b458]234
[b7fd2a0]235 errno_t retval;
[02a09ed]236 async_wait_for(req, &retval);
[a35b458]237
[25a179e]238 return retval;
[962f03b]239}
240
[8d48c7e]241void *iplink_get_userptr(iplink_t *iplink)
242{
243 return iplink->arg;
244}
245
[984a9ba]246static void iplink_ev_recv(iplink_t *iplink, ipc_call_t *icall)
[f834f90d]247{
[02a09ed]248 iplink_recv_sdu_t sdu;
[a35b458]249
[417a2ba1]250 ip_ver_t ver = IPC_GET_ARG1(*icall);
[a35b458]251
[b7fd2a0]252 errno_t rc = async_data_write_accept(&sdu.data, false, 0, 0, 0,
[02a09ed]253 &sdu.size);
[f834f90d]254 if (rc != EOK) {
[984a9ba]255 async_answer_0(icall, rc);
[f834f90d]256 return;
257 }
[a35b458]258
[417a2ba1]259 rc = iplink->ev_ops->recv(iplink, &sdu, ver);
[ffa8912]260 free(sdu.data);
[984a9ba]261 async_answer_0(icall, rc);
[f834f90d]262}
263
[984a9ba]264static void iplink_ev_change_addr(iplink_t *iplink, ipc_call_t *icall)
[c3b25985]265{
266 addr48_t *addr;
267 size_t size;
[a35b458]268
[984a9ba]269 errno_t rc = async_data_write_accept((void **) &addr, false,
[c3b25985]270 sizeof(addr48_t), sizeof(addr48_t), 0, &size);
271 if (rc != EOK) {
[984a9ba]272 async_answer_0(icall, rc);
[c3b25985]273 return;
274 }
275
276 rc = iplink->ev_ops->change_addr(iplink, *addr);
277 free(addr);
[984a9ba]278 async_answer_0(icall, EOK);
[c3b25985]279}
280
[984a9ba]281static void iplink_cb_conn(ipc_call_t *icall, void *arg)
[f834f90d]282{
[b5cf742a]283 iplink_t *iplink = (iplink_t *) arg;
[a35b458]284
[f834f90d]285 while (true) {
286 ipc_call_t call;
[984a9ba]287 async_get_call(&call);
[a35b458]288
[f834f90d]289 if (!IPC_GET_IMETHOD(call)) {
290 /* TODO: Handle hangup */
291 return;
292 }
[a35b458]293
[f834f90d]294 switch (IPC_GET_IMETHOD(call)) {
295 case IPLINK_EV_RECV:
[984a9ba]296 iplink_ev_recv(iplink, &call);
[f834f90d]297 break;
[c3b25985]298 case IPLINK_EV_CHANGE_ADDR:
[984a9ba]299 iplink_ev_change_addr(iplink, &call);
[dc12262]300 break;
[f834f90d]301 default:
[984a9ba]302 async_answer_0(&call, ENOTSUP);
[f834f90d]303 }
304 }
305}
306
307/** @}
308 */
Note: See TracBrowser for help on using the repository browser.