source: mainline/uspace/lib/c/generic/inet/udp.c@ 1d4b815

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 1d4b815 was 779541b, checked in by Jiri Svoboda <jiri@…>, 10 years ago

TCP transport layer API - somewhat working.

  • Property mode set to 100644
File size: 8.3 KB
RevLine 
[fab2746]1/*
2 * Copyright (c) 2015 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/** @addtogroup libc
30 * @{
31 */
32/** @file UDP API
33 */
34
35#include <errno.h>
36#include <inet/endpoint.h>
37#include <inet/udp.h>
38#include <io/log.h>
39#include <ipc/services.h>
40#include <ipc/udp.h>
41#include <loc.h>
42#include <stdlib.h>
43
44static void udp_cb_conn(ipc_callid_t, ipc_call_t *, void *);
45
46static int udp_callback_create(udp_t *udp)
47{
48 async_exch_t *exch = async_exchange_begin(udp->sess);
49
[779541b]50 log_msg(LOG_DEFAULT, LVL_NOTE, "udp_callback_create()");
[fab2746]51
52 aid_t req = async_send_0(exch, UDP_CALLBACK_CREATE, NULL);
53 int rc = async_connect_to_me(exch, 0, 0, 0, udp_cb_conn, udp);
54 async_exchange_end(exch);
55
56 if (rc != EOK)
57 return rc;
58
59 sysarg_t retval;
60 async_wait_for(req, &retval);
61
62 return retval;
63}
64
65int udp_create(udp_t **rudp)
66{
67 udp_t *udp;
68 service_id_t udp_svcid;
69 int rc;
70
[779541b]71 log_msg(LOG_DEFAULT, LVL_NOTE, "udp_create()");
[fab2746]72
73 udp = calloc(1, sizeof(udp_t));
74 if (udp == NULL) {
75 rc = ENOMEM;
76 goto error;
77 }
78
79 list_initialize(&udp->assoc);
80
81 rc = loc_service_get_id(SERVICE_NAME_UDP, &udp_svcid,
82 IPC_FLAG_BLOCKING);
83 if (rc != EOK) {
84 rc = EIO;
85 goto error;
86 }
87
88 udp->sess = loc_service_connect(EXCHANGE_SERIALIZE, udp_svcid,
89 IPC_FLAG_BLOCKING);
90 if (udp->sess == NULL) {
91 rc = EIO;
92 goto error;
93 }
94
95 rc = udp_callback_create(udp);
96 if (rc != EOK) {
97 rc = EIO;
98 goto error;
99 }
100
101 *rudp = udp;
102 return EOK;
103error:
104 free(udp);
105 return rc;
106}
107
108void udp_destroy(udp_t *udp)
109{
110 if (udp == NULL)
111 return;
112
113 async_hangup(udp->sess);
114 free(udp);
115}
116
117int udp_assoc_create(udp_t *udp, inet_ep2_t *ep2, udp_cb_t *cb, void *arg,
118 udp_assoc_t **rassoc)
119{
120 async_exch_t *exch;
121 udp_assoc_t *assoc;
122 ipc_call_t answer;
123
[779541b]124 log_msg(LOG_DEFAULT, LVL_NOTE, "udp_assoc_create()");
[fab2746]125
126 assoc = calloc(1, sizeof(udp_assoc_t));
127 if (assoc == NULL)
128 return ENOMEM;
129
130 exch = async_exchange_begin(udp->sess);
131 aid_t req = async_send_0(exch, UDP_ASSOC_CREATE, &answer);
132 sysarg_t rc = async_data_write_start(exch, (void *)ep2,
133 sizeof(inet_ep2_t));
134 async_exchange_end(exch);
135
136 if (rc != EOK) {
137 sysarg_t rc_orig;
138 async_wait_for(req, &rc_orig);
139 if (rc_orig != EOK)
140 rc = rc_orig;
141 goto error;
142 }
143
144 async_wait_for(req, &rc);
145 if (rc != EOK)
146 goto error;
147
148 assoc->udp = udp;
149 assoc->id = IPC_GET_ARG1(answer);
150 assoc->cb = cb;
151 assoc->cb_arg = arg;
152
153 list_append(&assoc->ludp, &udp->assoc);
154 *rassoc = assoc;
155
156 return EOK;
157error:
158 free(assoc);
159 return (int) rc;
160}
161
162void udp_assoc_destroy(udp_assoc_t *assoc)
163{
164 async_exch_t *exch;
165
[779541b]166 log_msg(LOG_DEFAULT, LVL_NOTE, "udp_assoc_destroy()");
[fab2746]167
168 if (assoc == NULL)
169 return;
170
171 list_remove(&assoc->ludp);
172
173 exch = async_exchange_begin(assoc->udp->sess);
174 sysarg_t rc = async_req_1_0(exch, UDP_ASSOC_DESTROY, assoc->id);
175 async_exchange_end(exch);
176
177 free(assoc);
178 (void) rc;
179}
180
181int udp_assoc_send_msg(udp_assoc_t *assoc, inet_ep_t *dest, void *data,
182 size_t bytes)
183{
184 async_exch_t *exch;
185
[779541b]186 log_msg(LOG_DEFAULT, LVL_NOTE, "udp_assoc_send_msg()");
[fab2746]187
188 exch = async_exchange_begin(assoc->udp->sess);
189 aid_t req = async_send_1(exch, UDP_ASSOC_SEND_MSG, assoc->id, NULL);
190
191 sysarg_t rc = async_data_write_start(exch, (void *)dest,
192 sizeof(inet_ep_t));
193 if (rc != EOK) {
194 async_exchange_end(exch);
195 async_forget(req);
196 return rc;
197 }
198
199 rc = async_data_write_start(exch, data, bytes);
200 if (rc != EOK) {
201 async_forget(req);
202 return rc;
203 }
204
205 async_exchange_end(exch);
206
207 if (rc != EOK) {
208 async_forget(req);
209 return rc;
210 }
211
212 async_wait_for(req, &rc);
213 return rc;
214}
215
216void *udp_assoc_userptr(udp_assoc_t *assoc)
217{
218 return assoc->cb_arg;
219}
220
221size_t udp_rmsg_size(udp_rmsg_t *rmsg)
222{
223 return rmsg->size;
224}
225
226int udp_rmsg_read(udp_rmsg_t *rmsg, size_t off, void *buf, size_t bsize)
227{
228 async_exch_t *exch;
229 ipc_call_t answer;
230
231 log_msg(LOG_DEFAULT, LVL_NOTE, "udp_rmsg_read()");
232
233 exch = async_exchange_begin(rmsg->udp->sess);
234 aid_t req = async_send_1(exch, UDP_RMSG_READ, off, &answer);
235 int rc = async_data_read_start(exch, buf, bsize);
236 async_exchange_end(exch);
237
238 if (rc != EOK) {
239 log_msg(LOG_DEFAULT, LVL_NOTE, "udp_rmsg_read() - rc != EOK");
240 async_forget(req);
241 return rc;
242 }
243
244 log_msg(LOG_DEFAULT, LVL_NOTE, "udp_rmsg_read() - wait for req");
245 sysarg_t retval;
246 async_wait_for(req, &retval);
247 if (retval != EOK) {
248 log_msg(LOG_DEFAULT, LVL_NOTE, "udp_rmsg_read() - retval != EOK");
249 return retval;
250 }
251
252 log_msg(LOG_DEFAULT, LVL_NOTE, "udp_rmsg_read() - OK");
253 return EOK;
254}
255
256void udp_rmsg_remote_ep(udp_rmsg_t *rmsg, inet_ep_t *ep)
257{
258 *ep = rmsg->remote_ep;
259}
260
261uint8_t udp_rerr_type(udp_rerr_t *rerr)
262{
263 return 0;
264}
265
266uint8_t udp_rerr_code(udp_rerr_t *rerr)
267{
268 return 0;
269}
270
271static int udp_rmsg_info(udp_t *udp, udp_rmsg_t *rmsg)
272{
273 async_exch_t *exch;
274 inet_ep_t ep;
275 ipc_call_t answer;
276
[779541b]277 log_msg(LOG_DEFAULT, LVL_NOTE, "udp_rmsg_info()");
[fab2746]278
279 exch = async_exchange_begin(udp->sess);
280 aid_t req = async_send_0(exch, UDP_RMSG_INFO, &answer);
281 int rc = async_data_read_start(exch, &ep, sizeof(inet_ep_t));
282 async_exchange_end(exch);
283
284 if (rc != EOK) {
285 async_forget(req);
286 return rc;
287 }
288
289 sysarg_t retval;
290 async_wait_for(req, &retval);
291 if (retval != EOK)
292 return retval;
293
294 rmsg->udp = udp;
295 rmsg->assoc_id = IPC_GET_ARG1(answer);
296 rmsg->size = IPC_GET_ARG2(answer);
297 rmsg->remote_ep = ep;
298 return EOK;
299}
300
301static int udp_rmsg_discard(udp_t *udp)
302{
303 async_exch_t *exch;
304
[779541b]305 log_msg(LOG_DEFAULT, LVL_NOTE, "udp_rmsg_discard()");
[fab2746]306
307 exch = async_exchange_begin(udp->sess);
308 sysarg_t rc = async_req_0_0(exch, UDP_RMSG_DISCARD);
309 async_exchange_end(exch);
310
311 return rc;
312}
313
314static int udp_assoc_get(udp_t *udp, sysarg_t id, udp_assoc_t **rassoc)
315{
316 list_foreach(udp->assoc, ludp, udp_assoc_t, assoc) {
317 if (assoc->id == id) {
318 *rassoc = assoc;
319 return EOK;
320 }
321 }
322
323 return EINVAL;
324}
325
326static void udp_ev_data(udp_t *udp, ipc_callid_t iid, ipc_call_t *icall)
327{
328 udp_rmsg_t rmsg;
329 udp_assoc_t *assoc;
330 int rc;
331
[779541b]332 log_msg(LOG_DEFAULT, LVL_NOTE, "udp_ev_data()");
[fab2746]333
334 while (true) {
335 rc = udp_rmsg_info(udp, &rmsg);
336 if (rc != EOK) {
[779541b]337 log_msg(LOG_DEFAULT, LVL_NOTE, "Error getting message info");
[fab2746]338 break;
339 }
340
341 rc = udp_assoc_get(udp, rmsg.assoc_id, &assoc);
342 if (rc != EOK) {
[779541b]343 log_msg(LOG_DEFAULT, LVL_NOTE, "assoc ID %zu not found",
[fab2746]344 rmsg.assoc_id);
345 continue;
346 }
347
348 if (assoc->cb != NULL && assoc->cb->recv_msg != NULL)
349 assoc->cb->recv_msg(assoc, &rmsg);
350
351 rc = udp_rmsg_discard(udp);
352 if (rc != EOK) {
[779541b]353 log_msg(LOG_DEFAULT, LVL_NOTE, "Error discarding message");
[fab2746]354 break;
355 }
356 }
357
358 async_answer_0(iid, EOK);
359}
360
361static void udp_cb_conn(ipc_callid_t iid, ipc_call_t *icall, void *arg)
362{
363 udp_t *udp = (udp_t *)arg;
364
365 async_answer_0(iid, EOK);
366
[779541b]367 log_msg(LOG_DEFAULT, LVL_NOTE, "udp_cb_conn()");
[fab2746]368
369 while (true) {
370 ipc_call_t call;
371 ipc_callid_t callid = async_get_call(&call);
372
[779541b]373 log_msg(LOG_DEFAULT, LVL_NOTE, "udp_cb_conn() - msg %d",
[fab2746]374 (int)IPC_GET_IMETHOD(call));
375 if (!IPC_GET_IMETHOD(call)) {
376 /* TODO: Handle hangup */
377 return;
378 }
379
380 switch (IPC_GET_IMETHOD(call)) {
381 case UDP_EV_DATA:
382 udp_ev_data(udp, callid, &call);
383 break;
384 default:
385 async_answer_0(callid, ENOTSUP);
386 break;
387 }
388 }
389}
390
391/** @}
392 */
Note: See TracBrowser for help on using the repository browser.