source: mainline/uspace/lib/c/generic/iplink_srv.c@ 99d3123

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