source: mainline/uspace/lib/c/generic/inetping.c@ 8610c2c

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 8610c2c 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: 5.5 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_callid_t, ipc_call_t *, void *);
41static void inetping_ev_recv(ipc_callid_t, ipc_call_t *);
42
43static async_sess_t *inetping_sess = NULL;
44static inetping_ev_ops_t *inetping_ev_ops;
45
46int inetping_init(inetping_ev_ops_t *ev_ops)
47{
48 service_id_t inetping_svc;
49 int 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
82int 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 int 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 int retval;
113 async_wait_for(req, &retval);
114
115 return retval;
116}
117
118int 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 int 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 int 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 int retval;
147 async_wait_for(req, &retval);
148
149 return retval;
150}
151
152static void inetping_ev_recv(ipc_callid_t iid, ipc_call_t *icall)
153{
154 inetping_sdu_t sdu;
155
156 sdu.seq_no = IPC_GET_ARG1(*icall);
157
158 ipc_callid_t callid;
159 size_t size;
160 if (!async_data_write_receive(&callid, &size)) {
161 async_answer_0(callid, EREFUSED);
162 async_answer_0(iid, EREFUSED);
163 return;
164 }
165
166 if (size != sizeof(sdu.src)) {
167 async_answer_0(callid, EINVAL);
168 async_answer_0(iid, EINVAL);
169 return;
170 }
171
172 int rc = async_data_write_finalize(callid, &sdu.src, size);
173 if (rc != EOK) {
174 async_answer_0(callid, rc);
175 async_answer_0(iid, rc);
176 return;
177 }
178
179 if (!async_data_write_receive(&callid, &size)) {
180 async_answer_0(callid, EREFUSED);
181 async_answer_0(iid, EREFUSED);
182 return;
183 }
184
185 if (size != sizeof(sdu.dest)) {
186 async_answer_0(callid, EINVAL);
187 async_answer_0(iid, EINVAL);
188 return;
189 }
190
191 rc = async_data_write_finalize(callid, &sdu.dest, size);
192 if (rc != EOK) {
193 async_answer_0(callid, rc);
194 async_answer_0(iid, 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(iid, rc);
201 return;
202 }
203
204 rc = inetping_ev_ops->recv(&sdu);
205 free(sdu.data);
206 async_answer_0(iid, rc);
207}
208
209static void inetping_cb_conn(ipc_callid_t iid, ipc_call_t *icall, void *arg)
210{
211 while (true) {
212 ipc_call_t call;
213 ipc_callid_t callid = 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(callid, &call);
223 break;
224 default:
225 async_answer_0(callid, ENOTSUP);
226 }
227 }
228}
229
230/** @}
231 */
Note: See TracBrowser for help on using the repository browser.