source: mainline/uspace/lib/c/generic/inet.c@ 25a179e

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 25a179e was 25a179e, checked in by Jiří Zárevúcky <zarevucky.jiri@…>, 8 years ago

IPC return values are always errno constants. Adjust types to reflect that.

In principle, IPC server is not allowed to return non-errno values via
the "main" return value, because kernel interprets it (e.g. EHANGUP).
It's still possible to return arbitrary additional return values alongside EOK,
which are not interpreted in normal communication.

  • Property mode set to 100644
File size: 6.0 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_callid_t iid, 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 int 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 int 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 int retval;
61 async_wait_for(req, &retval);
62
63 return retval;
64}
65
66static int inet_set_proto(uint8_t protocol)
67{
68 async_exch_t *exch = async_exchange_begin(inet_sess);
69 int rc = async_req_1_0(exch, INET_SET_PROTO, protocol);
70 async_exchange_end(exch);
71
72 return rc;
73}
74
75int inet_init(uint8_t protocol, inet_ev_ops_t *ev_ops)
76{
77 service_id_t inet_svc;
78 int 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
112int 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 int 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 int retval;
144 async_wait_for(req, &retval);
145
146 return retval;
147}
148
149int 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 int 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 int retval;
173 async_wait_for(req, &retval);
174
175 return retval;
176}
177
178static void inet_ev_recv(ipc_callid_t iid, 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_callid_t callid;
186 size_t size;
187 if (!async_data_write_receive(&callid, &size)) {
188 async_answer_0(callid, EINVAL);
189 async_answer_0(iid, EINVAL);
190 return;
191 }
192
193 if (size != sizeof(inet_addr_t)) {
194 async_answer_0(callid, EINVAL);
195 async_answer_0(iid, EINVAL);
196 return;
197 }
198
199 int rc = async_data_write_finalize(callid, &dgram.src, size);
200 if (rc != EOK) {
201 async_answer_0(callid, rc);
202 async_answer_0(iid, rc);
203 return;
204 }
205
206 if (!async_data_write_receive(&callid, &size)) {
207 async_answer_0(callid, EINVAL);
208 async_answer_0(iid, EINVAL);
209 return;
210 }
211
212 if (size != sizeof(inet_addr_t)) {
213 async_answer_0(callid, EINVAL);
214 async_answer_0(iid, EINVAL);
215 return;
216 }
217
218 rc = async_data_write_finalize(callid, &dgram.dest, size);
219 if (rc != EOK) {
220 async_answer_0(callid, rc);
221 async_answer_0(iid, 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(iid, rc);
228 return;
229 }
230
231 rc = inet_ev_ops->recv(&dgram);
232 free(dgram.data);
233 async_answer_0(iid, rc);
234}
235
236static void inet_cb_conn(ipc_callid_t iid, ipc_call_t *icall, void *arg)
237{
238 while (true) {
239 ipc_call_t call;
240 ipc_callid_t callid = 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(callid, &call);
250 break;
251 default:
252 async_answer_0(callid, ENOTSUP);
253 }
254 }
255}
256
257/** @}
258 */
Note: See TracBrowser for help on using the repository browser.