source: mainline/uspace/srv/net/udp/service.c@ 648e2ac

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

Mechanically lowercase IPC_SET_*/IPC_GET_*

  • Property mode set to 100644
File size: 17.1 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 *
[984a9ba]328 * @param client UDP client
329 * @param icall Async request data
330 *
[b10460a]331 */
[984a9ba]332static void udp_callback_create_srv(udp_client_t *client, ipc_call_t *icall)
[fab2746]333{
334 log_msg(LOG_DEFAULT, LVL_DEBUG, "udp_callback_create_srv()");
335
336 async_sess_t *sess = async_callback_receive(EXCHANGE_SERIALIZE);
337 if (sess == NULL) {
[984a9ba]338 async_answer_0(icall, ENOMEM);
[fab2746]339 return;
340 }
341
342 client->sess = sess;
[984a9ba]343 async_answer_0(icall, EOK);
[fab2746]344}
345
[b10460a]346/** Create association.
347 *
348 * Handle client request to create association.
349 *
[984a9ba]350 * @param client UDP client
351 * @param icall Async request data
352 *
[b10460a]353 */
[984a9ba]354static void udp_assoc_create_srv(udp_client_t *client, ipc_call_t *icall)
[fab2746]355{
[984a9ba]356 ipc_call_t call;
[fab2746]357 size_t size;
358 inet_ep2_t epp;
359 sysarg_t assoc_id;
[b7fd2a0]360 errno_t rc;
[fab2746]361
362 log_msg(LOG_DEFAULT, LVL_DEBUG, "udp_assoc_create_srv()");
363
[984a9ba]364 if (!async_data_write_receive(&call, &size)) {
365 async_answer_0(&call, EREFUSED);
366 async_answer_0(icall, EREFUSED);
[fab2746]367 return;
368 }
369
370 if (size != sizeof(inet_ep2_t)) {
[984a9ba]371 async_answer_0(&call, EINVAL);
372 async_answer_0(icall, EINVAL);
[fab2746]373 return;
374 }
375
[984a9ba]376 rc = async_data_write_finalize(&call, &epp, size);
[fab2746]377 if (rc != EOK) {
[984a9ba]378 async_answer_0(&call, rc);
379 async_answer_0(icall, rc);
[fab2746]380 return;
381 }
382
383 rc = udp_assoc_create_impl(client, &epp, &assoc_id);
384 if (rc != EOK) {
[984a9ba]385 async_answer_0(icall, rc);
[fab2746]386 return;
387 }
388
[984a9ba]389 async_answer_1(icall, EOK, assoc_id);
[fab2746]390}
391
[b10460a]392/** Destroy association.
393 *
394 * Handle client request to destroy association.
395 *
[984a9ba]396 * @param client UDP client
397 * @param icall Async request data
398 *
[b10460a]399 */
[984a9ba]400static void udp_assoc_destroy_srv(udp_client_t *client, ipc_call_t *icall)
[fab2746]401{
402 sysarg_t assoc_id;
[b7fd2a0]403 errno_t rc;
[fab2746]404
405 log_msg(LOG_DEFAULT, LVL_DEBUG, "udp_assoc_destroy_srv()");
406
[fafb8e5]407 assoc_id = ipc_get_arg1(icall);
[fab2746]408 rc = udp_assoc_destroy_impl(client, assoc_id);
[984a9ba]409 async_answer_0(icall, rc);
[fab2746]410}
411
[58e8646]412/** Set association with no local address.
413 *
414 * Handle client request to set no local address flag.
415 *
[984a9ba]416 * @param client UDP client
417 * @param icall Async request data
418 *
[58e8646]419 */
[984a9ba]420static void udp_assoc_set_nolocal_srv(udp_client_t *client, ipc_call_t *icall)
[58e8646]421{
422 sysarg_t assoc_id;
[b7fd2a0]423 errno_t rc;
[58e8646]424
425 log_msg(LOG_DEFAULT, LVL_NOTE, "udp_assoc_set_nolocal_srv()");
426
[fafb8e5]427 assoc_id = ipc_get_arg1(icall);
[58e8646]428 rc = udp_assoc_set_nolocal_impl(client, assoc_id);
[984a9ba]429 async_answer_0(icall, rc);
[58e8646]430}
431
[b10460a]432/** Send message via association.
433 *
434 * Handle client request to send message.
435 *
[984a9ba]436 * @param client UDP client
437 * @param icall Async request data
438 *
[b10460a]439 */
[984a9ba]440static void udp_assoc_send_msg_srv(udp_client_t *client, ipc_call_t *icall)
[fab2746]441{
[984a9ba]442 ipc_call_t call;
[fab2746]443 size_t size;
444 inet_ep_t dest;
445 sysarg_t assoc_id;
446 void *data;
[b7fd2a0]447 errno_t rc;
[fab2746]448
449 log_msg(LOG_DEFAULT, LVL_DEBUG, "udp_assoc_send_msg_srv()");
450
451 /* Receive dest */
452
[984a9ba]453 if (!async_data_write_receive(&call, &size)) {
454 async_answer_0(&call, EREFUSED);
455 async_answer_0(icall, EREFUSED);
[fab2746]456 return;
457 }
458
459 if (size != sizeof(inet_ep_t)) {
[984a9ba]460 async_answer_0(&call, EINVAL);
461 async_answer_0(icall, EINVAL);
[fab2746]462 return;
463 }
464
[984a9ba]465 rc = async_data_write_finalize(&call, &dest, size);
[fab2746]466 if (rc != EOK) {
[984a9ba]467 async_answer_0(&call, rc);
468 async_answer_0(icall, rc);
[fab2746]469 return;
470 }
471
472 /* Receive message data */
473
[984a9ba]474 if (!async_data_write_receive(&call, &size)) {
475 async_answer_0(&call, EREFUSED);
476 async_answer_0(icall, EREFUSED);
[fab2746]477 return;
478 }
479
480 if (size > MAX_MSG_SIZE) {
[984a9ba]481 async_answer_0(&call, EINVAL);
482 async_answer_0(icall, EINVAL);
[fab2746]483 return;
484 }
485
486 data = malloc(size);
487 if (data == NULL) {
[984a9ba]488 async_answer_0(&call, ENOMEM);
489 async_answer_0(icall, ENOMEM);
[fab2746]490 }
491
[984a9ba]492 rc = async_data_write_finalize(&call, data, size);
[fab2746]493 if (rc != EOK) {
[984a9ba]494 async_answer_0(&call, rc);
495 async_answer_0(icall, rc);
[fab2746]496 free(data);
497 return;
498 }
499
[fafb8e5]500 assoc_id = ipc_get_arg1(icall);
[fab2746]501
502 rc = udp_assoc_send_msg_impl(client, assoc_id, &dest, data, size);
503 if (rc != EOK) {
[984a9ba]504 async_answer_0(icall, rc);
[fab2746]505 free(data);
506 return;
507 }
508
[984a9ba]509 async_answer_0(icall, EOK);
[fab2746]510 free(data);
511}
512
[b10460a]513/** Get next received message.
514 *
515 * @param client UDP Client
516 * @return Pointer to queue entry for next received message
517 */
[fab2746]518static udp_crcv_queue_entry_t *udp_rmsg_get_next(udp_client_t *client)
519{
520 link_t *link;
521
522 link = list_first(&client->crcv_queue);
523 if (link == NULL)
524 return NULL;
525
526 return list_get_instance(link, udp_crcv_queue_entry_t, link);
527}
528
[b10460a]529/** Get info on first received message.
530 *
531 * Handle client request to get information on received message.
532 *
[984a9ba]533 * @param client UDP client
534 * @param icall Async request data
535 *
[b10460a]536 */
[984a9ba]537static void udp_rmsg_info_srv(udp_client_t *client, ipc_call_t *icall)
[fab2746]538{
[984a9ba]539 ipc_call_t call;
[fab2746]540 size_t size;
541 udp_crcv_queue_entry_t *enext;
542 sysarg_t assoc_id;
[b7fd2a0]543 errno_t rc;
[fab2746]544
545 log_msg(LOG_DEFAULT, LVL_DEBUG, "udp_rmsg_info_srv()");
546 enext = udp_rmsg_get_next(client);
547
[984a9ba]548 if (!async_data_read_receive(&call, &size)) {
549 async_answer_0(&call, EREFUSED);
550 async_answer_0(icall, EREFUSED);
[fab2746]551 return;
552 }
553
554 if (enext == NULL) {
[984a9ba]555 async_answer_0(&call, ENOENT);
556 async_answer_0(icall, ENOENT);
[fab2746]557 return;
558 }
559
[984a9ba]560 rc = async_data_read_finalize(&call, &enext->epp.remote,
[bde5c04]561 max(size, (size_t)sizeof(inet_ep_t)));
[fab2746]562 if (rc != EOK) {
[984a9ba]563 async_answer_0(icall, rc);
[fab2746]564 return;
565 }
566
567 assoc_id = enext->cassoc->id;
568 size = enext->msg->data_size;
569
570 log_msg(LOG_DEFAULT, LVL_DEBUG, "udp_rmsg_info_srv(): assoc_id=%zu, "
571 "size=%zu", assoc_id, size);
[984a9ba]572 async_answer_2(icall, EOK, assoc_id, size);
[fab2746]573}
574
[b10460a]575/** Read data from first received message.
576 *
577 * Handle client request to read data from first received message.
578 *
[984a9ba]579 * @param client UDP client
580 * @param icall Async request data
581 *
[b10460a]582 */
[984a9ba]583static void udp_rmsg_read_srv(udp_client_t *client, ipc_call_t *icall)
[fab2746]584{
[984a9ba]585 ipc_call_t call;
[bde5c04]586 size_t msg_size;
[fab2746]587 udp_crcv_queue_entry_t *enext;
588 void *data;
589 size_t size;
[bde5c04]590 size_t off;
[b7fd2a0]591 errno_t rc;
[fab2746]592
593 log_msg(LOG_DEFAULT, LVL_DEBUG, "udp_rmsg_read_srv()");
[fafb8e5]594 off = ipc_get_arg1(icall);
[fab2746]595
596 enext = udp_rmsg_get_next(client);
597
[984a9ba]598 if (!async_data_read_receive(&call, &size)) {
599 async_answer_0(&call, EREFUSED);
600 async_answer_0(icall, EREFUSED);
[fab2746]601 return;
602 }
603
604 if (enext == NULL) {
[984a9ba]605 async_answer_0(&call, ENOENT);
606 async_answer_0(icall, ENOENT);
[fab2746]607 return;
608 }
609
610 data = enext->msg->data + off;
611 msg_size = enext->msg->data_size;
612
[bde5c04]613 if (off > msg_size) {
[984a9ba]614 async_answer_0(&call, EINVAL);
615 async_answer_0(icall, EINVAL);
[bde5c04]616 return;
617 }
618
[984a9ba]619 rc = async_data_read_finalize(&call, data, min(msg_size - off, size));
[fab2746]620 if (rc != EOK) {
[984a9ba]621 async_answer_0(icall, rc);
[fab2746]622 return;
623 }
624
[984a9ba]625 async_answer_0(icall, EOK);
[fab2746]626 log_msg(LOG_DEFAULT, LVL_DEBUG, "udp_rmsg_read_srv(): OK");
627}
628
[b10460a]629/** Discard first received message.
630 *
631 * Handle client request to discard first received message, advancing
632 * to the next one.
633 *
[984a9ba]634 * @param client UDP client
635 * @param icall Async request data
636 *
[b10460a]637 */
[984a9ba]638static void udp_rmsg_discard_srv(udp_client_t *client, ipc_call_t *icall)
[fab2746]639{
640 udp_crcv_queue_entry_t *enext;
641
642 log_msg(LOG_DEFAULT, LVL_DEBUG, "udp_rmsg_discard_srv()");
643
644 enext = udp_rmsg_get_next(client);
645 if (enext == NULL) {
[99ea91b2]646 log_msg(LOG_DEFAULT, LVL_DEBUG, "usg_rmsg_discard_srv: enext==NULL");
[984a9ba]647 async_answer_0(icall, ENOENT);
[fab2746]648 return;
649 }
650
651 list_remove(&enext->link);
652 udp_msg_delete(enext->msg);
[99ea91b2]653 free(enext);
[984a9ba]654 async_answer_0(icall, EOK);
[fab2746]655}
656
[b10460a]657/** Handle UDP client connection.
658 *
[984a9ba]659 * @param icall Connect call data
660 * @param arg Connection argument
661 *
[b10460a]662 */
[984a9ba]663static void udp_client_conn(ipc_call_t *icall, void *arg)
[fab2746]664{
665 udp_client_t client;
[be12474]666 unsigned long n;
[fab2746]667
668 /* Accept the connection */
[beb83c1]669 async_accept_0(icall);
[fab2746]670
671 log_msg(LOG_DEFAULT, LVL_DEBUG, "udp_client_conn()");
672
[1f2b07a]673 client.sess = NULL;
[fab2746]674 list_initialize(&client.cassoc);
675 list_initialize(&client.crcv_queue);
676
677 while (true) {
[99ea91b2]678 log_msg(LOG_DEFAULT, LVL_DEBUG, "udp_client_conn: wait req");
[fab2746]679 ipc_call_t call;
[984a9ba]680 async_get_call(&call);
[fafb8e5]681 sysarg_t method = ipc_get_imethod(&call);
[fab2746]682
[99ea91b2]683 log_msg(LOG_DEFAULT, LVL_DEBUG, "udp_client_conn: method=%d",
[fab2746]684 (int)method);
685 if (!method) {
686 /* The other side has hung up */
[984a9ba]687 async_answer_0(&call, EOK);
[309469de]688 break;
[fab2746]689 }
690
691 switch (method) {
692 case UDP_CALLBACK_CREATE:
[984a9ba]693 udp_callback_create_srv(&client, &call);
[fab2746]694 break;
695 case UDP_ASSOC_CREATE:
[984a9ba]696 udp_assoc_create_srv(&client, &call);
[fab2746]697 break;
698 case UDP_ASSOC_DESTROY:
[984a9ba]699 udp_assoc_destroy_srv(&client, &call);
[fab2746]700 break;
[58e8646]701 case UDP_ASSOC_SET_NOLOCAL:
[984a9ba]702 udp_assoc_set_nolocal_srv(&client, &call);
[58e8646]703 break;
[fab2746]704 case UDP_ASSOC_SEND_MSG:
[984a9ba]705 udp_assoc_send_msg_srv(&client, &call);
[fab2746]706 break;
707 case UDP_RMSG_INFO:
[984a9ba]708 udp_rmsg_info_srv(&client, &call);
[fab2746]709 break;
710 case UDP_RMSG_READ:
[984a9ba]711 udp_rmsg_read_srv(&client, &call);
[fab2746]712 break;
713 case UDP_RMSG_DISCARD:
[984a9ba]714 udp_rmsg_discard_srv(&client, &call);
[fab2746]715 break;
716 default:
[984a9ba]717 async_answer_0(&call, ENOTSUP);
[fab2746]718 break;
719 }
720 }
[309469de]721
722 log_msg(LOG_DEFAULT, LVL_DEBUG, "udp_client_conn: terminated");
723
724 n = list_count(&client.cassoc);
725 if (n != 0) {
726 log_msg(LOG_DEFAULT, LVL_WARN, "udp_client_conn: "
[1d03e86]727 "Client with %lu active associations closed session.", n);
[309469de]728 /* XXX Clean up */
729 }
730
731 /* XXX Clean up client receive queue */
[1f2b07a]732
733 if (client.sess != NULL)
734 async_hangup(client.sess);
[fab2746]735}
736
[b10460a]737/** Initialize UDP service.
738 *
[cde999a]739 * @return EOK on success or an error code.
[b10460a]740 */
[b7fd2a0]741errno_t udp_service_init(void)
[fab2746]742{
[b7fd2a0]743 errno_t rc;
[fab2746]744 service_id_t sid;
745
[b688fd8]746 async_set_fallback_port_handler(udp_client_conn, NULL);
[fab2746]747
748 rc = loc_server_register(NAME);
749 if (rc != EOK) {
750 log_msg(LOG_DEFAULT, LVL_ERROR, "Failed registering server.");
751 return EIO;
752 }
753
754 rc = loc_service_register(SERVICE_NAME_UDP, &sid);
755 if (rc != EOK) {
756 log_msg(LOG_DEFAULT, LVL_ERROR, "Failed registering service.");
757 return EIO;
758 }
759
760 return EOK;
761}
762
763/**
764 * @}
765 */
Note: See TracBrowser for help on using the repository browser.