source: mainline/uspace/lib/c/generic/inetping6.c@ e948fde

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since e948fde was f5f79cd, checked in by Martin Decky <martin@…>, 12 years ago

fix client-side protocol implementation

  • Property mode set to 100644
File size: 5.5 KB
Line 
1/*
2 * Copyright (c) 2013 Martin Decky
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/inetping6.h>
33#include <ipc/inet.h>
34#include <ipc/services.h>
35#include <loc.h>
36#include <stdlib.h>
37#include <str.h>
38
39static void inetping6_cb_conn(ipc_callid_t, ipc_call_t *, void *);
40static void inetping6_ev_recv(ipc_callid_t, ipc_call_t *);
41
42static async_sess_t *inetping6_sess = NULL;
43static inetping6_ev_ops_t *inetping6_ev_ops;
44
45int inetping6_init(inetping6_ev_ops_t *ev_ops)
46{
47 assert(inetping6_sess == NULL);
48
49 inetping6_ev_ops = ev_ops;
50
51 service_id_t inetping6_svc;
52 int rc = loc_service_get_id(SERVICE_NAME_INETPING6, &inetping6_svc,
53 IPC_FLAG_BLOCKING);
54 if (rc != EOK)
55 return ENOENT;
56
57 inetping6_sess = loc_service_connect(EXCHANGE_SERIALIZE, inetping6_svc,
58 IPC_FLAG_BLOCKING);
59 if (inetping6_sess == NULL)
60 return ENOENT;
61
62 async_exch_t *exch = async_exchange_begin(inetping6_sess);
63
64 rc = async_connect_to_me(exch, 0, 0, 0, inetping6_cb_conn, NULL);
65 async_exchange_end(exch);
66
67 if (rc != EOK) {
68 async_hangup(inetping6_sess);
69 inetping6_sess = NULL;
70 return rc;
71 }
72
73 return EOK;
74}
75
76int inetping6_send(inetping6_sdu_t *sdu)
77{
78 async_exch_t *exch = async_exchange_begin(inetping6_sess);
79
80 ipc_call_t answer;
81 aid_t req = async_send_1(exch, INETPING6_SEND, sdu->seq_no, &answer);
82
83 int rc = async_data_write_start(exch, &sdu->src, sizeof(addr128_t));
84 if (rc != EOK) {
85 async_exchange_end(exch);
86 async_forget(req);
87 return rc;
88 }
89
90 rc = async_data_write_start(exch, &sdu->dest, sizeof(addr128_t));
91 if (rc != EOK) {
92 async_exchange_end(exch);
93 async_forget(req);
94 return rc;
95 }
96
97 rc = async_data_write_start(exch, sdu->data, sdu->size);
98
99 async_exchange_end(exch);
100
101 if (rc != EOK) {
102 async_forget(req);
103 return rc;
104 }
105
106 sysarg_t retval;
107 async_wait_for(req, &retval);
108
109 return (int) retval;
110}
111
112int inetping6_get_srcaddr(addr128_t remote, addr128_t local)
113{
114 async_exch_t *exch = async_exchange_begin(inetping6_sess);
115
116 ipc_call_t answer;
117 aid_t req = async_send_0(exch, INETPING6_GET_SRCADDR, &answer);
118
119 int rc = async_data_write_start(exch, remote, sizeof(addr128_t));
120 if (rc != EOK) {
121 async_exchange_end(exch);
122 async_forget(req);
123 return rc;
124 }
125
126 ipc_call_t answer_local;
127 aid_t req_local = async_data_read(exch, local, sizeof(addr128_t),
128 &answer_local);
129
130 async_exchange_end(exch);
131
132 sysarg_t retval_local;
133 async_wait_for(req_local, &retval_local);
134
135 if (retval_local != EOK) {
136 async_forget(req);
137 return (int) retval_local;
138 }
139
140 sysarg_t retval;
141 async_wait_for(req, &retval);
142
143 return (int) retval;
144}
145
146static void inetping6_ev_recv(ipc_callid_t iid, ipc_call_t *icall)
147{
148 inetping6_sdu_t sdu;
149
150 sdu.seq_no = IPC_GET_ARG1(*icall);
151
152 ipc_callid_t callid;
153 size_t size;
154 if (!async_data_write_receive(&callid, &size)) {
155 async_answer_0(callid, EREFUSED);
156 async_answer_0(iid, EREFUSED);
157 return;
158 }
159
160 if (size != sizeof(addr128_t)) {
161 async_answer_0(callid, EINVAL);
162 async_answer_0(iid, EINVAL);
163 return;
164 }
165
166 int rc = async_data_write_finalize(callid, &sdu.src, size);
167 if (rc != EOK) {
168 async_answer_0(callid, rc);
169 async_answer_0(iid, rc);
170 return;
171 }
172
173 if (!async_data_write_receive(&callid, &size)) {
174 async_answer_0(callid, EREFUSED);
175 async_answer_0(iid, EREFUSED);
176 return;
177 }
178
179 if (size != sizeof(addr128_t)) {
180 async_answer_0(callid, EINVAL);
181 async_answer_0(iid, EINVAL);
182 return;
183 }
184
185 rc = async_data_write_finalize(callid, &sdu.dest, size);
186 if (rc != EOK) {
187 async_answer_0(callid, rc);
188 async_answer_0(iid, rc);
189 return;
190 }
191
192 rc = async_data_write_accept(&sdu.data, false, 0, 0, 0, &sdu.size);
193 if (rc != EOK) {
194 async_answer_0(iid, rc);
195 return;
196 }
197
198 rc = inetping6_ev_ops->recv(&sdu);
199 free(sdu.data);
200 async_answer_0(iid, rc);
201}
202
203static void inetping6_cb_conn(ipc_callid_t iid, ipc_call_t *icall, void *arg)
204{
205 while (true) {
206 ipc_call_t call;
207 ipc_callid_t callid = async_get_call(&call);
208
209 if (!IPC_GET_IMETHOD(call)) {
210 /* TODO: Handle hangup */
211 return;
212 }
213
214 switch (IPC_GET_IMETHOD(call)) {
215 case INETPING6_EV_RECV:
216 inetping6_ev_recv(callid, &call);
217 break;
218 default:
219 async_answer_0(callid, ENOTSUP);
220 }
221 }
222}
223
224/** @}
225 */
Note: See TracBrowser for help on using the repository browser.