source: mainline/uspace/lib/c/generic/inet.c@ 514d561

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 514d561 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.9 KB
Line 
1/*
2 * Copyright (c) 2013 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#include <async.h>
30#include <assert.h>
31#include <errno.h>
32#include <inet/inet.h>
33#include <ipc/inet.h>
34#include <ipc/services.h>
35#include <loc.h>
36#include <stdlib.h>
37
38static void inet_cb_conn(ipc_call_t *icall, void *arg);
39
40static async_sess_t *inet_sess = NULL;
41static inet_ev_ops_t *inet_ev_ops = NULL;
42static uint8_t inet_protocol = 0;
43
44static errno_t inet_callback_create(void)
45{
46 async_exch_t *exch = async_exchange_begin(inet_sess);
47
48 ipc_call_t answer;
49 aid_t req = async_send_0(exch, INET_CALLBACK_CREATE, &answer);
50
51 port_id_t port;
52 errno_t rc = async_create_callback_port(exch, INTERFACE_INET_CB, 0, 0,
53 inet_cb_conn, NULL, &port);
54
55 async_exchange_end(exch);
56
57 if (rc != EOK)
58 return rc;
59
60 errno_t retval;
61 async_wait_for(req, &retval);
62
63 return retval;
64}
65
66static errno_t inet_set_proto(uint8_t protocol)
67{
68 async_exch_t *exch = async_exchange_begin(inet_sess);
69 errno_t rc = async_req_1_0(exch, INET_SET_PROTO, protocol);
70 async_exchange_end(exch);
71
72 return rc;
73}
74
75errno_t inet_init(uint8_t protocol, inet_ev_ops_t *ev_ops)
76{
77 service_id_t inet_svc;
78 errno_t rc;
79
80 assert(inet_sess == NULL);
81 assert(inet_ev_ops == NULL);
82 assert(inet_protocol == 0);
83
84 rc = loc_service_get_id(SERVICE_NAME_INET, &inet_svc,
85 IPC_FLAG_BLOCKING);
86 if (rc != EOK)
87 return ENOENT;
88
89 inet_sess = loc_service_connect(inet_svc, INTERFACE_INET,
90 IPC_FLAG_BLOCKING);
91 if (inet_sess == NULL)
92 return ENOENT;
93
94 if (inet_set_proto(protocol) != EOK) {
95 async_hangup(inet_sess);
96 inet_sess = NULL;
97 return EIO;
98 }
99
100 if (inet_callback_create() != EOK) {
101 async_hangup(inet_sess);
102 inet_sess = NULL;
103 return EIO;
104 }
105
106 inet_protocol = protocol;
107 inet_ev_ops = ev_ops;
108
109 return EOK;
110}
111
112errno_t inet_send(inet_dgram_t *dgram, uint8_t ttl, inet_df_t df)
113{
114 async_exch_t *exch = async_exchange_begin(inet_sess);
115
116 ipc_call_t answer;
117 aid_t req = async_send_4(exch, INET_SEND, dgram->iplink, dgram->tos,
118 ttl, df, &answer);
119
120 errno_t rc = async_data_write_start(exch, &dgram->src, sizeof(inet_addr_t));
121 if (rc != EOK) {
122 async_exchange_end(exch);
123 async_forget(req);
124 return rc;
125 }
126
127 rc = async_data_write_start(exch, &dgram->dest, sizeof(inet_addr_t));
128 if (rc != EOK) {
129 async_exchange_end(exch);
130 async_forget(req);
131 return rc;
132 }
133
134 rc = async_data_write_start(exch, dgram->data, dgram->size);
135
136 async_exchange_end(exch);
137
138 if (rc != EOK) {
139 async_forget(req);
140 return rc;
141 }
142
143 errno_t retval;
144 async_wait_for(req, &retval);
145
146 return retval;
147}
148
149errno_t inet_get_srcaddr(inet_addr_t *remote, uint8_t tos, inet_addr_t *local)
150{
151 async_exch_t *exch = async_exchange_begin(inet_sess);
152
153 ipc_call_t answer;
154 aid_t req = async_send_1(exch, INET_GET_SRCADDR, tos, &answer);
155
156 errno_t rc = async_data_write_start(exch, remote, sizeof(inet_addr_t));
157 if (rc != EOK) {
158 async_exchange_end(exch);
159 async_forget(req);
160 return rc;
161 }
162
163 rc = async_data_read_start(exch, local, sizeof(inet_addr_t));
164
165 async_exchange_end(exch);
166
167 if (rc != EOK) {
168 async_forget(req);
169 return rc;
170 }
171
172 errno_t retval;
173 async_wait_for(req, &retval);
174
175 return retval;
176}
177
178static void inet_ev_recv(ipc_call_t *icall)
179{
180 inet_dgram_t dgram;
181
182 dgram.tos = IPC_GET_ARG1(*icall);
183 dgram.iplink = IPC_GET_ARG2(*icall);
184
185 ipc_call_t call;
186 size_t size;
187 if (!async_data_write_receive(&call, &size)) {
188 async_answer_0(&call, EINVAL);
189 async_answer_0(icall, EINVAL);
190 return;
191 }
192
193 if (size != sizeof(inet_addr_t)) {
194 async_answer_0(&call, EINVAL);
195 async_answer_0(icall, EINVAL);
196 return;
197 }
198
199 errno_t rc = async_data_write_finalize(&call, &dgram.src, size);
200 if (rc != EOK) {
201 async_answer_0(&call, rc);
202 async_answer_0(icall, rc);
203 return;
204 }
205
206 if (!async_data_write_receive(&call, &size)) {
207 async_answer_0(&call, EINVAL);
208 async_answer_0(icall, EINVAL);
209 return;
210 }
211
212 if (size != sizeof(inet_addr_t)) {
213 async_answer_0(&call, EINVAL);
214 async_answer_0(icall, EINVAL);
215 return;
216 }
217
218 rc = async_data_write_finalize(&call, &dgram.dest, size);
219 if (rc != EOK) {
220 async_answer_0(&call, rc);
221 async_answer_0(icall, rc);
222 return;
223 }
224
225 rc = async_data_write_accept(&dgram.data, false, 0, 0, 0, &dgram.size);
226 if (rc != EOK) {
227 async_answer_0(icall, rc);
228 return;
229 }
230
231 rc = inet_ev_ops->recv(&dgram);
232 free(dgram.data);
233 async_answer_0(icall, rc);
234}
235
236static void inet_cb_conn(ipc_call_t *icall, void *arg)
237{
238 while (true) {
239 ipc_call_t call;
240 async_get_call(&call);
241
242 if (!IPC_GET_IMETHOD(call)) {
243 /* TODO: Handle hangup */
244 return;
245 }
246
247 switch (IPC_GET_IMETHOD(call)) {
248 case INET_EV_RECV:
249 inet_ev_recv(&call);
250 break;
251 default:
252 async_answer_0(&call, ENOTSUP);
253 }
254 }
255}
256
257/** @}
258 */
Note: See TracBrowser for help on using the repository browser.