source: mainline/uspace/srv/net/udp/service.c@ 3fafe5e0

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

Fix incorrectly indented double-slash comments.

  • Property mode set to 100644
File size: 18.4 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 udp
30 * @{
31 */
32
33/**
34 * @file HelenOS service implementation
35 */
36
37#include <async.h>
38#include <errno.h>
39#include <inet/endpoint.h>
40#include <io/log.h>
41#include <ipc/services.h>
42#include <ipc/udp.h>
43#include <loc.h>
44#include <macros.h>
45#include <stdlib.h>
46
47#include "assoc.h"
48#include "msg.h"
49#include "service.h"
50#include "udp_type.h"
51
52#define NAME "udp"
53
[b10460a]54/** Maximum message size */
[fab2746]55#define MAX_MSG_SIZE DATA_XFER_LIMIT
56
[2f19103]57static void udp_cassoc_recv_msg(void *, inet_ep2_t *, udp_msg_t *);
[fab2746]58
[b10460a]59/** Callbacks to tie us to association layer */
[fab2746]60static udp_assoc_cb_t udp_cassoc_cb = {
61 .recv_msg = udp_cassoc_recv_msg
62};
63
[b10460a]64/** Add message to client receive queue.
65 *
66 * @param cassoc Client association
67 * @param epp Endpoint pair on which message was received
68 * @param msg Message
69 *
70 * @return EOK on success, ENOMEM if out of memory
71 */
[b7fd2a0]72static errno_t udp_cassoc_queue_msg(udp_cassoc_t *cassoc, inet_ep2_t *epp,
[fab2746]73 udp_msg_t *msg)
74{
75 udp_crcv_queue_entry_t *rqe;
76
[99ea91b2]77 log_msg(LOG_DEFAULT, LVL_DEBUG, "udp_cassoc_queue_msg(%p, %p, %p)",
[2f19103]78 cassoc, epp, msg);
[fab2746]79
80 rqe = calloc(1, sizeof(udp_crcv_queue_entry_t));
81 if (rqe == NULL)
82 return ENOMEM;
83
84 link_initialize(&rqe->link);
[2f19103]85 rqe->epp = *epp;
[fab2746]86 rqe->msg = msg;
87 rqe->cassoc = cassoc;
88
89 list_append(&rqe->link, &cassoc->client->crcv_queue);
90 return EOK;
91}
92
[b10460a]93/** Send 'data' event to client.
94 *
95 * @param client Client
96 */
[99ea91b2]97static void udp_ev_data(udp_client_t *client)
[fab2746]98{
99 async_exch_t *exch;
100
[99ea91b2]101 log_msg(LOG_DEFAULT, LVL_DEBUG, "udp_ev_data()");
[fab2746]102
103 exch = async_exchange_begin(client->sess);
[99ea91b2]104 aid_t req = async_send_0(exch, UDP_EV_DATA, NULL);
[fab2746]105 async_exchange_end(exch);
106
[99ea91b2]107 async_forget(req);
[fab2746]108}
109
[b10460a]110/** Create client association.
111 *
112 * This effectively adds an association into a client's namespace.
113 *
114 * @param client Client
115 * @param assoc Association
116 * @param rcassoc Place to store pointer to new client association
117 *
118 * @return EOK on soccess, ENOMEM if out of memory
119 */
[b7fd2a0]120static errno_t udp_cassoc_create(udp_client_t *client, udp_assoc_t *assoc,
[fab2746]121 udp_cassoc_t **rcassoc)
122{
123 udp_cassoc_t *cassoc;
124 sysarg_t id;
125
126 cassoc = calloc(1, sizeof(udp_cassoc_t));
127 if (cassoc == NULL)
128 return ENOMEM;
129
130 /* Allocate new ID */
131 id = 0;
132 list_foreach (client->cassoc, lclient, udp_cassoc_t, cassoc) {
133 if (cassoc->id >= id)
134 id = cassoc->id + 1;
135 }
136
137 cassoc->id = id;
138 cassoc->client = client;
139 cassoc->assoc = assoc;
140
141 list_append(&cassoc->lclient, &client->cassoc);
142 *rcassoc = cassoc;
143 return EOK;
144}
145
[b10460a]146/** Destroy client association.
147 *
148 * @param cassoc Client association
149 */
[fab2746]150static void udp_cassoc_destroy(udp_cassoc_t *cassoc)
151{
152 list_remove(&cassoc->lclient);
153 free(cassoc);
154}
155
[b10460a]156/** Get client association by ID.
157 *
158 * @param client Client
159 * @param id Client association ID
160 * @param rcassoc Place to store pointer to client association
161 *
162 * @return EOK on success, ENOENT if no client association with the given ID
163 * is found.
164 */
[b7fd2a0]165static errno_t udp_cassoc_get(udp_client_t *client, sysarg_t id,
[fab2746]166 udp_cassoc_t **rcassoc)
167{
168 list_foreach (client->cassoc, lclient, udp_cassoc_t, cassoc) {
169 if (cassoc->id == id) {
170 *rcassoc = cassoc;
171 return EOK;
172 }
173 }
174
175 return ENOENT;
176}
177
[b10460a]178/** Message received on client association.
179 *
180 * Used as udp_assoc_cb.recv_msg callback.
181 *
182 * @param arg Callback argument, client association
183 * @param epp Endpoint pair where message was received
184 * @param msg Message
185 */
[2f19103]186static void udp_cassoc_recv_msg(void *arg, inet_ep2_t *epp, udp_msg_t *msg)
[fab2746]187{
188 udp_cassoc_t *cassoc = (udp_cassoc_t *) arg;
189
[2f19103]190 udp_cassoc_queue_msg(cassoc, epp, msg);
[fab2746]191 udp_ev_data(cassoc->client);
192}
193
[b10460a]194/** Create association.
195 *
196 * Handle client request to create association (with parameters unmarshalled).
197 *
198 * @param client UDP client
199 * @param epp Endpoint pair
200 * @param rassoc_id Place to store ID of new association
201 *
[cde999a]202 * @return EOK on success or an error code
[b10460a]203 */
[b7fd2a0]204static errno_t udp_assoc_create_impl(udp_client_t *client, inet_ep2_t *epp,
[fab2746]205 sysarg_t *rassoc_id)
206{
207 udp_assoc_t *assoc;
208 udp_cassoc_t *cassoc;
[b7fd2a0]209 errno_t rc;
[779541b]210
211 log_msg(LOG_DEFAULT, LVL_DEBUG, "udp_assoc_create_impl");
[fab2746]212
[2f19103]213 assoc = udp_assoc_new(epp, NULL, NULL);
[fab2746]214 if (assoc == NULL)
215 return EIO;
216
217 if (epp->local_link != 0)
218 udp_assoc_set_iplink(assoc, epp->local_link);
219
220 rc = udp_cassoc_create(client, assoc, &cassoc);
221 if (rc != EOK) {
222 assert(rc == ENOMEM);
223 udp_assoc_delete(assoc);
224 return ENOMEM;
225 }
226
227 assoc->cb = &udp_cassoc_cb;
228 assoc->cb_arg = cassoc;
229
[2989c7e]230 rc = udp_assoc_add(assoc);
231 if (rc != EOK) {
232 udp_cassoc_destroy(cassoc);
233 udp_assoc_delete(assoc);
234 return rc;
235 }
[fab2746]236
237 *rassoc_id = cassoc->id;
238 return EOK;
239}
240
[b10460a]241/** Destroy association.
242 *
243 * Handle client request to destroy association (with parameters unmarshalled).
244 *
245 * @param client UDP client
246 * @param assoc_id Association ID
247 * @return EOK on success, ENOENT if no such association is found
248 */
[b7fd2a0]249static errno_t udp_assoc_destroy_impl(udp_client_t *client, sysarg_t assoc_id)
[fab2746]250{
251 udp_cassoc_t *cassoc;
[b7fd2a0]252 errno_t rc;
[fab2746]253
254 rc = udp_cassoc_get(client, assoc_id, &cassoc);
255 if (rc != EOK) {
256 assert(rc == ENOENT);
257 return ENOENT;
258 }
259
260 udp_assoc_remove(cassoc->assoc);
261 udp_assoc_reset(cassoc->assoc);
262 udp_assoc_delete(cassoc->assoc);
263 udp_cassoc_destroy(cassoc);
264 return EOK;
265}
266
[58e8646]267/** Set association sending messages with no local address.
268 *
269 * Handle client request to set nolocal flag (with parameters unmarshalled).
270 *
271 * @param client UDP client
272 * @param assoc_id Association ID
273 * @return EOK on success, ENOENT if no such association is found
274 */
[b7fd2a0]275static errno_t udp_assoc_set_nolocal_impl(udp_client_t *client, sysarg_t assoc_id)
[58e8646]276{
277 udp_cassoc_t *cassoc;
[b7fd2a0]278 errno_t rc;
[58e8646]279
280 rc = udp_cassoc_get(client, assoc_id, &cassoc);
281 if (rc != EOK) {
282 assert(rc == ENOENT);
283 return ENOENT;
284 }
285
286 log_msg(LOG_DEFAULT, LVL_NOTE, "Setting nolocal to true");
287 cassoc->assoc->nolocal = true;
288 return EOK;
289}
290
[b10460a]291/** Send message via association.
292 *
293 * Handle client request to send message (with parameters unmarshalled).
294 *
295 * @param client UDP client
296 * @param assoc_id Association ID
297 * @param dest Destination endpoint or @c NULL to use the default from
298 * association
299 * @param data Message data
300 * @param size Message size
301 *
[cde999a]302 * @return EOK on success or an error code
[b10460a]303 */
[b7fd2a0]304static errno_t udp_assoc_send_msg_impl(udp_client_t *client, sysarg_t assoc_id,
[fab2746]305 inet_ep_t *dest, void *data, size_t size)
306{
307 udp_msg_t msg;
308 udp_cassoc_t *cassoc;
[b7fd2a0]309 errno_t rc;
[fab2746]310
311 rc = udp_cassoc_get(client, assoc_id, &cassoc);
312 if (rc != EOK)
313 return rc;
314
315 msg.data = data;
316 msg.data_size = size;
[2f19103]317 rc = udp_assoc_send(cassoc->assoc, dest, &msg);
[fab2746]318 if (rc != EOK)
319 return rc;
320
321 return EOK;
322}
323
[b10460a]324/** Create callback session.
325 *
326 * Handle client request to create callback session.
327 *
[cbb37b6]328 * @param client UDP client
[b752a31]329 * @param icall_handle Async request call handle
[cbb37b6]330 * @param icall Async request data
[b10460a]331 */
[cbb37b6]332static void
333udp_callback_create_srv(udp_client_t *client, cap_call_handle_t icall_handle,
[fab2746]334 ipc_call_t *icall)
335{
336 log_msg(LOG_DEFAULT, LVL_DEBUG, "udp_callback_create_srv()");
337
338 async_sess_t *sess = async_callback_receive(EXCHANGE_SERIALIZE);
339 if (sess == NULL) {
[a46e56b]340 async_answer_0(icall_handle, ENOMEM);
[fab2746]341 return;
342 }
343
344 client->sess = sess;
[a46e56b]345 async_answer_0(icall_handle, EOK);
[fab2746]346}
347
[b10460a]348/** Create association.
349 *
350 * Handle client request to create association.
351 *
[cbb37b6]352 * @param client UDP client
353 * @param icall_handle Async request call handle
354 * @param icall Async request data
[b10460a]355 */
[18b6a88]356static void
357udp_assoc_create_srv(udp_client_t *client, cap_call_handle_t icall_handle,
[fab2746]358 ipc_call_t *icall)
359{
[a46e56b]360 cap_call_handle_t chandle;
[fab2746]361 size_t size;
362 inet_ep2_t epp;
363 sysarg_t assoc_id;
[b7fd2a0]364 errno_t rc;
[fab2746]365
366 log_msg(LOG_DEFAULT, LVL_DEBUG, "udp_assoc_create_srv()");
367
[a46e56b]368 if (!async_data_write_receive(&chandle, &size)) {
369 async_answer_0(chandle, EREFUSED);
370 async_answer_0(icall_handle, EREFUSED);
[fab2746]371 return;
372 }
373
374 if (size != sizeof(inet_ep2_t)) {
[a46e56b]375 async_answer_0(chandle, EINVAL);
376 async_answer_0(icall_handle, EINVAL);
[fab2746]377 return;
378 }
379
[a46e56b]380 rc = async_data_write_finalize(chandle, &epp, size);
[fab2746]381 if (rc != EOK) {
[a46e56b]382 async_answer_0(chandle, rc);
383 async_answer_0(icall_handle, rc);
[fab2746]384 return;
385 }
386
387 rc = udp_assoc_create_impl(client, &epp, &assoc_id);
388 if (rc != EOK) {
[a46e56b]389 async_answer_0(icall_handle, rc);
[fab2746]390 return;
391 }
392
[a46e56b]393 async_answer_1(icall_handle, EOK, assoc_id);
[fab2746]394}
395
[b10460a]396/** Destroy association.
397 *
398 * Handle client request to destroy association.
399 *
[cbb37b6]400 * @param client UDP client
401 * @param icall_handle Async request call handle
402 * @param icall Async request data
[b10460a]403 */
[cbb37b6]404static void
405udp_assoc_destroy_srv(udp_client_t *client, cap_call_handle_t icall_handle,
[fab2746]406 ipc_call_t *icall)
407{
408 sysarg_t assoc_id;
[b7fd2a0]409 errno_t rc;
[fab2746]410
411 log_msg(LOG_DEFAULT, LVL_DEBUG, "udp_assoc_destroy_srv()");
412
413 assoc_id = IPC_GET_ARG1(*icall);
414 rc = udp_assoc_destroy_impl(client, assoc_id);
[a46e56b]415 async_answer_0(icall_handle, rc);
[fab2746]416}
417
[58e8646]418/** Set association with no local address.
419 *
420 * Handle client request to set no local address flag.
421 *
[cbb37b6]422 * @param client UDP client
423 * @param icall_handle Async request call handle
424 * @param icall Async request data
[58e8646]425 */
[cbb37b6]426static void
427udp_assoc_set_nolocal_srv(udp_client_t *client, cap_call_handle_t icall_handle,
[58e8646]428 ipc_call_t *icall)
429{
430 sysarg_t assoc_id;
[b7fd2a0]431 errno_t rc;
[58e8646]432
433 log_msg(LOG_DEFAULT, LVL_NOTE, "udp_assoc_set_nolocal_srv()");
434
435 assoc_id = IPC_GET_ARG1(*icall);
436 rc = udp_assoc_set_nolocal_impl(client, assoc_id);
[a46e56b]437 async_answer_0(icall_handle, rc);
[58e8646]438}
439
[b10460a]440/** Send message via association.
441 *
442 * Handle client request to send message.
443 *
[cbb37b6]444 * @param client UDP client
[b752a31]445 * @param icall_handle Async request call handle
[cbb37b6]446 * @param icall Async request data
[b10460a]447 */
[cbb37b6]448static void
449udp_assoc_send_msg_srv(udp_client_t *client, cap_call_handle_t icall_handle,
[fab2746]450 ipc_call_t *icall)
451{
[a46e56b]452 cap_call_handle_t chandle;
[fab2746]453 size_t size;
454 inet_ep_t dest;
455 sysarg_t assoc_id;
456 void *data;
[b7fd2a0]457 errno_t rc;
[fab2746]458
459 log_msg(LOG_DEFAULT, LVL_DEBUG, "udp_assoc_send_msg_srv()");
460
461 /* Receive dest */
462
[a46e56b]463 if (!async_data_write_receive(&chandle, &size)) {
464 async_answer_0(chandle, EREFUSED);
465 async_answer_0(icall_handle, EREFUSED);
[fab2746]466 return;
467 }
468
469 if (size != sizeof(inet_ep_t)) {
[a46e56b]470 async_answer_0(chandle, EINVAL);
471 async_answer_0(icall_handle, EINVAL);
[fab2746]472 return;
473 }
474
[a46e56b]475 rc = async_data_write_finalize(chandle, &dest, size);
[fab2746]476 if (rc != EOK) {
[a46e56b]477 async_answer_0(chandle, rc);
478 async_answer_0(icall_handle, rc);
[fab2746]479 return;
480 }
481
482 /* Receive message data */
483
[a46e56b]484 if (!async_data_write_receive(&chandle, &size)) {
485 async_answer_0(chandle, EREFUSED);
486 async_answer_0(icall_handle, EREFUSED);
[fab2746]487 return;
488 }
489
490 if (size > MAX_MSG_SIZE) {
[a46e56b]491 async_answer_0(chandle, EINVAL);
492 async_answer_0(icall_handle, EINVAL);
[fab2746]493 return;
494 }
495
496 data = malloc(size);
497 if (data == NULL) {
[a46e56b]498 async_answer_0(chandle, ENOMEM);
499 async_answer_0(icall_handle, ENOMEM);
[fab2746]500 }
501
[a46e56b]502 rc = async_data_write_finalize(chandle, data, size);
[fab2746]503 if (rc != EOK) {
[a46e56b]504 async_answer_0(chandle, rc);
505 async_answer_0(icall_handle, rc);
[fab2746]506 free(data);
507 return;
508 }
509
510 assoc_id = IPC_GET_ARG1(*icall);
511
512 rc = udp_assoc_send_msg_impl(client, assoc_id, &dest, data, size);
513 if (rc != EOK) {
[a46e56b]514 async_answer_0(icall_handle, rc);
[fab2746]515 free(data);
516 return;
517 }
518
[a46e56b]519 async_answer_0(icall_handle, EOK);
[fab2746]520 free(data);
521}
522
[b10460a]523/** Get next received message.
524 *
525 * @param client UDP Client
526 * @return Pointer to queue entry for next received message
527 */
[fab2746]528static udp_crcv_queue_entry_t *udp_rmsg_get_next(udp_client_t *client)
529{
530 link_t *link;
531
532 link = list_first(&client->crcv_queue);
533 if (link == NULL)
534 return NULL;
535
536 return list_get_instance(link, udp_crcv_queue_entry_t, link);
537}
538
[b10460a]539/** Get info on first received message.
540 *
541 * Handle client request to get information on received message.
542 *
[cbb37b6]543 * @param client UDP client
544 * @param icall_handle Async request call handle
545 * @param icall Async request data
[b10460a]546 */
[cbb37b6]547static void
548udp_rmsg_info_srv(udp_client_t *client, cap_call_handle_t icall_handle,
[fab2746]549 ipc_call_t *icall)
550{
[a46e56b]551 cap_call_handle_t chandle;
[fab2746]552 size_t size;
553 udp_crcv_queue_entry_t *enext;
554 sysarg_t assoc_id;
[b7fd2a0]555 errno_t rc;
[fab2746]556
557 log_msg(LOG_DEFAULT, LVL_DEBUG, "udp_rmsg_info_srv()");
558 enext = udp_rmsg_get_next(client);
559
[a46e56b]560 if (!async_data_read_receive(&chandle, &size)) {
561 async_answer_0(chandle, EREFUSED);
562 async_answer_0(icall_handle, EREFUSED);
[fab2746]563 return;
564 }
565
566 if (enext == NULL) {
[a46e56b]567 async_answer_0(chandle, ENOENT);
568 async_answer_0(icall_handle, ENOENT);
[fab2746]569 return;
570 }
571
[a46e56b]572 rc = async_data_read_finalize(chandle, &enext->epp.remote,
[bde5c04]573 max(size, (size_t)sizeof(inet_ep_t)));
[fab2746]574 if (rc != EOK) {
[a46e56b]575 async_answer_0(icall_handle, rc);
[fab2746]576 return;
577 }
578
579 assoc_id = enext->cassoc->id;
580 size = enext->msg->data_size;
581
582 log_msg(LOG_DEFAULT, LVL_DEBUG, "udp_rmsg_info_srv(): assoc_id=%zu, "
583 "size=%zu", assoc_id, size);
[a46e56b]584 async_answer_2(icall_handle, EOK, assoc_id, size);
[fab2746]585}
586
[b10460a]587/** Read data from first received message.
588 *
589 * Handle client request to read data from first received message.
590 *
[cbb37b6]591 * @param client UDP client
592 * @param icall_handle Async request call handle
593 * @param icall Async request data
[b10460a]594 */
[cbb37b6]595static void
596udp_rmsg_read_srv(udp_client_t *client, cap_call_handle_t icall_handle,
[fab2746]597 ipc_call_t *icall)
598{
[a46e56b]599 cap_call_handle_t chandle;
[bde5c04]600 size_t msg_size;
[fab2746]601 udp_crcv_queue_entry_t *enext;
602 void *data;
603 size_t size;
[bde5c04]604 size_t off;
[b7fd2a0]605 errno_t rc;
[fab2746]606
607 log_msg(LOG_DEFAULT, LVL_DEBUG, "udp_rmsg_read_srv()");
608 off = IPC_GET_ARG1(*icall);
609
610 enext = udp_rmsg_get_next(client);
611
[a46e56b]612 if (!async_data_read_receive(&chandle, &size)) {
613 async_answer_0(chandle, EREFUSED);
614 async_answer_0(icall_handle, EREFUSED);
[fab2746]615 return;
616 }
617
618 if (enext == NULL) {
[a46e56b]619 async_answer_0(chandle, ENOENT);
620 async_answer_0(icall_handle, ENOENT);
[fab2746]621 return;
622 }
623
624 data = enext->msg->data + off;
625 msg_size = enext->msg->data_size;
626
[bde5c04]627 if (off > msg_size) {
[a46e56b]628 async_answer_0(chandle, EINVAL);
629 async_answer_0(icall_handle, EINVAL);
[bde5c04]630 return;
631 }
632
[a46e56b]633 rc = async_data_read_finalize(chandle, data, min(msg_size - off, size));
[fab2746]634 if (rc != EOK) {
[a46e56b]635 async_answer_0(icall_handle, rc);
[fab2746]636 return;
637 }
638
[a46e56b]639 async_answer_0(icall_handle, EOK);
[fab2746]640 log_msg(LOG_DEFAULT, LVL_DEBUG, "udp_rmsg_read_srv(): OK");
641}
642
[b10460a]643/** Discard first received message.
644 *
645 * Handle client request to discard first received message, advancing
646 * to the next one.
647 *
[cbb37b6]648 * @param client UDP client
649 * @param icall_handle Async request call handle
650 * @param icall Async request data
[b10460a]651 */
[cbb37b6]652static void
653udp_rmsg_discard_srv(udp_client_t *client, cap_call_handle_t icall_handle,
[fab2746]654 ipc_call_t *icall)
655{
656 udp_crcv_queue_entry_t *enext;
657
658 log_msg(LOG_DEFAULT, LVL_DEBUG, "udp_rmsg_discard_srv()");
659
660 enext = udp_rmsg_get_next(client);
661 if (enext == NULL) {
[99ea91b2]662 log_msg(LOG_DEFAULT, LVL_DEBUG, "usg_rmsg_discard_srv: enext==NULL");
[a46e56b]663 async_answer_0(icall_handle, ENOENT);
[fab2746]664 return;
665 }
666
667 list_remove(&enext->link);
668 udp_msg_delete(enext->msg);
[99ea91b2]669 free(enext);
[a46e56b]670 async_answer_0(icall_handle, EOK);
[fab2746]671}
672
[b10460a]673/** Handle UDP client connection.
674 *
[b752a31]675 * @param icall_handle Connect call handle
[eed4139]676 * @param icall Connect call data
677 * @param arg Connection argument
[b10460a]678 */
[eed4139]679static void udp_client_conn(cap_call_handle_t icall_handle, ipc_call_t *icall,
680 void *arg)
[fab2746]681{
682 udp_client_t client;
[be12474]683 unsigned long n;
[fab2746]684
685 /* Accept the connection */
[a46e56b]686 async_answer_0(icall_handle, EOK);
[fab2746]687
688 log_msg(LOG_DEFAULT, LVL_DEBUG, "udp_client_conn()");
689
[1f2b07a]690 client.sess = NULL;
[fab2746]691 list_initialize(&client.cassoc);
692 list_initialize(&client.crcv_queue);
693
694 while (true) {
[99ea91b2]695 log_msg(LOG_DEFAULT, LVL_DEBUG, "udp_client_conn: wait req");
[fab2746]696 ipc_call_t call;
[a46e56b]697 cap_call_handle_t chandle = async_get_call(&call);
[fab2746]698 sysarg_t method = IPC_GET_IMETHOD(call);
699
[99ea91b2]700 log_msg(LOG_DEFAULT, LVL_DEBUG, "udp_client_conn: method=%d",
[fab2746]701 (int)method);
702 if (!method) {
703 /* The other side has hung up */
[a46e56b]704 async_answer_0(chandle, EOK);
[309469de]705 break;
[fab2746]706 }
707
708 switch (method) {
709 case UDP_CALLBACK_CREATE:
[a46e56b]710 udp_callback_create_srv(&client, chandle, &call);
[fab2746]711 break;
712 case UDP_ASSOC_CREATE:
[a46e56b]713 udp_assoc_create_srv(&client, chandle, &call);
[fab2746]714 break;
715 case UDP_ASSOC_DESTROY:
[a46e56b]716 udp_assoc_destroy_srv(&client, chandle, &call);
[fab2746]717 break;
[58e8646]718 case UDP_ASSOC_SET_NOLOCAL:
[a46e56b]719 udp_assoc_set_nolocal_srv(&client, chandle, &call);
[58e8646]720 break;
[fab2746]721 case UDP_ASSOC_SEND_MSG:
[a46e56b]722 udp_assoc_send_msg_srv(&client, chandle, &call);
[fab2746]723 break;
724 case UDP_RMSG_INFO:
[a46e56b]725 udp_rmsg_info_srv(&client, chandle, &call);
[fab2746]726 break;
727 case UDP_RMSG_READ:
[a46e56b]728 udp_rmsg_read_srv(&client, chandle, &call);
[fab2746]729 break;
730 case UDP_RMSG_DISCARD:
[a46e56b]731 udp_rmsg_discard_srv(&client, chandle, &call);
[fab2746]732 break;
733 default:
[a46e56b]734 async_answer_0(chandle, ENOTSUP);
[fab2746]735 break;
736 }
737 }
[309469de]738
739 log_msg(LOG_DEFAULT, LVL_DEBUG, "udp_client_conn: terminated");
740
741 n = list_count(&client.cassoc);
742 if (n != 0) {
743 log_msg(LOG_DEFAULT, LVL_WARN, "udp_client_conn: "
[1d03e86]744 "Client with %lu active associations closed session.", n);
[309469de]745 /* XXX Clean up */
746 }
747
748 /* XXX Clean up client receive queue */
[1f2b07a]749
750 if (client.sess != NULL)
751 async_hangup(client.sess);
[fab2746]752}
753
[b10460a]754/** Initialize UDP service.
755 *
[cde999a]756 * @return EOK on success or an error code.
[b10460a]757 */
[b7fd2a0]758errno_t udp_service_init(void)
[fab2746]759{
[b7fd2a0]760 errno_t rc;
[fab2746]761 service_id_t sid;
762
[b688fd8]763 async_set_fallback_port_handler(udp_client_conn, NULL);
[fab2746]764
765 rc = loc_server_register(NAME);
766 if (rc != EOK) {
767 log_msg(LOG_DEFAULT, LVL_ERROR, "Failed registering server.");
768 return EIO;
769 }
770
771 rc = loc_service_register(SERVICE_NAME_UDP, &sid);
772 if (rc != EOK) {
773 log_msg(LOG_DEFAULT, LVL_ERROR, "Failed registering service.");
774 return EIO;
775 }
776
777 return EOK;
778}
779
780/**
781 * @}
782 */
Note: See TracBrowser for help on using the repository browser.