source: mainline/uspace/lib/c/generic/inetping.c@ 63d46341

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 63d46341 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.4 KB
Line 
1/*
2 * Copyright (c) 2013 Jiri Svoboda
3 * Copyright (c) 2013 Martin Decky
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#include <async.h>
31#include <assert.h>
32#include <errno.h>
33#include <inet/inetping.h>
34#include <ipc/inet.h>
35#include <ipc/services.h>
36#include <loc.h>
37#include <stdlib.h>
38#include <str.h>
39
40static void inetping_cb_conn(ipc_call_t *, void *);
41static void inetping_ev_recv(ipc_call_t *);
42
43static async_sess_t *inetping_sess = NULL;
44static inetping_ev_ops_t *inetping_ev_ops;
45
46errno_t inetping_init(inetping_ev_ops_t *ev_ops)
47{
48 service_id_t inetping_svc;
49 errno_t rc;
50
51 assert(inetping_sess == NULL);
52
53 inetping_ev_ops = ev_ops;
54
55 rc = loc_service_get_id(SERVICE_NAME_INET, &inetping_svc,
56 IPC_FLAG_BLOCKING);
57 if (rc != EOK)
58 return ENOENT;
59
60 inetping_sess = loc_service_connect(inetping_svc, INTERFACE_INETPING,
61 IPC_FLAG_BLOCKING);
62 if (inetping_sess == NULL)
63 return ENOENT;
64
65 async_exch_t *exch = async_exchange_begin(inetping_sess);
66
67 port_id_t port;
68 rc = async_create_callback_port(exch, INTERFACE_INETPING_CB, 0, 0,
69 inetping_cb_conn, NULL, &port);
70
71 async_exchange_end(exch);
72
73 if (rc != EOK) {
74 async_hangup(inetping_sess);
75 inetping_sess = NULL;
76 return rc;
77 }
78
79 return EOK;
80}
81
82errno_t inetping_send(inetping_sdu_t *sdu)
83{
84 async_exch_t *exch = async_exchange_begin(inetping_sess);
85
86 ipc_call_t answer;
87 aid_t req = async_send_1(exch, INETPING_SEND, sdu->seq_no, &answer);
88
89 errno_t rc = async_data_write_start(exch, &sdu->src, sizeof(sdu->src));
90 if (rc != EOK) {
91 async_exchange_end(exch);
92 async_forget(req);
93 return rc;
94 }
95
96 rc = async_data_write_start(exch, &sdu->dest, sizeof(sdu->dest));
97 if (rc != EOK) {
98 async_exchange_end(exch);
99 async_forget(req);
100 return rc;
101 }
102
103 rc = async_data_write_start(exch, sdu->data, sdu->size);
104
105 async_exchange_end(exch);
106
107 if (rc != EOK) {
108 async_forget(req);
109 return rc;
110 }
111
112 errno_t retval;
113 async_wait_for(req, &retval);
114
115 return retval;
116}
117
118errno_t inetping_get_srcaddr(const inet_addr_t *remote, inet_addr_t *local)
119{
120 async_exch_t *exch = async_exchange_begin(inetping_sess);
121
122 ipc_call_t answer;
123 aid_t req = async_send_0(exch, INETPING_GET_SRCADDR, &answer);
124
125 errno_t rc = async_data_write_start(exch, remote, sizeof(*remote));
126 if (rc != EOK) {
127 async_exchange_end(exch);
128 async_forget(req);
129 return rc;
130 }
131
132 ipc_call_t answer_local;
133 aid_t req_local = async_data_read(exch, local, sizeof(*local),
134 &answer_local);
135
136 async_exchange_end(exch);
137
138 errno_t retval_local;
139 async_wait_for(req_local, &retval_local);
140
141 if (retval_local != EOK) {
142 async_forget(req);
143 return retval_local;
144 }
145
146 errno_t retval;
147 async_wait_for(req, &retval);
148
149 return retval;
150}
151
152static void inetping_ev_recv(ipc_call_t *icall)
153{
154 inetping_sdu_t sdu;
155
156 sdu.seq_no = IPC_GET_ARG1(*icall);
157
158 ipc_call_t call;
159 size_t size;
160 if (!async_data_write_receive(&call, &size)) {
161 async_answer_0(&call, EREFUSED);
162 async_answer_0(icall, EREFUSED);
163 return;
164 }
165
166 if (size != sizeof(sdu.src)) {
167 async_answer_0(&call, EINVAL);
168 async_answer_0(icall, EINVAL);
169 return;
170 }
171
172 errno_t rc = async_data_write_finalize(&call, &sdu.src, size);
173 if (rc != EOK) {
174 async_answer_0(&call, rc);
175 async_answer_0(icall, rc);
176 return;
177 }
178
179 if (!async_data_write_receive(&call, &size)) {
180 async_answer_0(&call, EREFUSED);
181 async_answer_0(icall, EREFUSED);
182 return;
183 }
184
185 if (size != sizeof(sdu.dest)) {
186 async_answer_0(&call, EINVAL);
187 async_answer_0(icall, EINVAL);
188 return;
189 }
190
191 rc = async_data_write_finalize(&call, &sdu.dest, size);
192 if (rc != EOK) {
193 async_answer_0(&call, rc);
194 async_answer_0(icall, rc);
195 return;
196 }
197
198 rc = async_data_write_accept(&sdu.data, false, 0, 0, 0, &sdu.size);
199 if (rc != EOK) {
200 async_answer_0(icall, rc);
201 return;
202 }
203
204 rc = inetping_ev_ops->recv(&sdu);
205 free(sdu.data);
206 async_answer_0(icall, rc);
207}
208
209static void inetping_cb_conn(ipc_call_t *icall, void *arg)
210{
211 while (true) {
212 ipc_call_t call;
213 async_get_call(&call);
214
215 if (!IPC_GET_IMETHOD(call)) {
216 /* TODO: Handle hangup */
217 return;
218 }
219
220 switch (IPC_GET_IMETHOD(call)) {
221 case INETPING_EV_RECV:
222 inetping_ev_recv(&call);
223 break;
224 default:
225 async_answer_0(&call, ENOTSUP);
226 }
227 }
228}
229
230/** @}
231 */
Note: See TracBrowser for help on using the repository browser.