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
Line 
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
54/** Maximum message size */
55#define MAX_MSG_SIZE DATA_XFER_LIMIT
56
57static void udp_cassoc_recv_msg(void *, inet_ep2_t *, udp_msg_t *);
58
59/** Callbacks to tie us to association layer */
60static udp_assoc_cb_t udp_cassoc_cb = {
61 .recv_msg = udp_cassoc_recv_msg
62};
63
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 */
72static errno_t udp_cassoc_queue_msg(udp_cassoc_t *cassoc, inet_ep2_t *epp,
73 udp_msg_t *msg)
74{
75 udp_crcv_queue_entry_t *rqe;
76
77 log_msg(LOG_DEFAULT, LVL_DEBUG, "udp_cassoc_queue_msg(%p, %p, %p)",
78 cassoc, epp, msg);
79
80 rqe = calloc(1, sizeof(udp_crcv_queue_entry_t));
81 if (rqe == NULL)
82 return ENOMEM;
83
84 link_initialize(&rqe->link);
85 rqe->epp = *epp;
86 rqe->msg = msg;
87 rqe->cassoc = cassoc;
88
89 list_append(&rqe->link, &cassoc->client->crcv_queue);
90 return EOK;
91}
92
93/** Send 'data' event to client.
94 *
95 * @param client Client
96 */
97static void udp_ev_data(udp_client_t *client)
98{
99 async_exch_t *exch;
100
101 log_msg(LOG_DEFAULT, LVL_DEBUG, "udp_ev_data()");
102
103 exch = async_exchange_begin(client->sess);
104 aid_t req = async_send_0(exch, UDP_EV_DATA, NULL);
105 async_exchange_end(exch);
106
107 async_forget(req);
108}
109
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 */
120static errno_t udp_cassoc_create(udp_client_t *client, udp_assoc_t *assoc,
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
146/** Destroy client association.
147 *
148 * @param cassoc Client association
149 */
150static void udp_cassoc_destroy(udp_cassoc_t *cassoc)
151{
152 list_remove(&cassoc->lclient);
153 free(cassoc);
154}
155
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 */
165static errno_t udp_cassoc_get(udp_client_t *client, sysarg_t id,
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
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 */
186static void udp_cassoc_recv_msg(void *arg, inet_ep2_t *epp, udp_msg_t *msg)
187{
188 udp_cassoc_t *cassoc = (udp_cassoc_t *) arg;
189
190 udp_cassoc_queue_msg(cassoc, epp, msg);
191 udp_ev_data(cassoc->client);
192}
193
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 *
202 * @return EOK on success or an error code
203 */
204static errno_t udp_assoc_create_impl(udp_client_t *client, inet_ep2_t *epp,
205 sysarg_t *rassoc_id)
206{
207 udp_assoc_t *assoc;
208 udp_cassoc_t *cassoc;
209 errno_t rc;
210
211 log_msg(LOG_DEFAULT, LVL_DEBUG, "udp_assoc_create_impl");
212
213 assoc = udp_assoc_new(epp, NULL, NULL);
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
230 rc = udp_assoc_add(assoc);
231 if (rc != EOK) {
232 udp_cassoc_destroy(cassoc);
233 udp_assoc_delete(assoc);
234 return rc;
235 }
236
237 *rassoc_id = cassoc->id;
238 return EOK;
239}
240
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 */
249static errno_t udp_assoc_destroy_impl(udp_client_t *client, sysarg_t assoc_id)
250{
251 udp_cassoc_t *cassoc;
252 errno_t rc;
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
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 */
275static errno_t udp_assoc_set_nolocal_impl(udp_client_t *client, sysarg_t assoc_id)
276{
277 udp_cassoc_t *cassoc;
278 errno_t rc;
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
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 *
302 * @return EOK on success or an error code
303 */
304static errno_t udp_assoc_send_msg_impl(udp_client_t *client, sysarg_t assoc_id,
305 inet_ep_t *dest, void *data, size_t size)
306{
307 udp_msg_t msg;
308 udp_cassoc_t *cassoc;
309 errno_t rc;
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;
317 rc = udp_assoc_send(cassoc->assoc, dest, &msg);
318 if (rc != EOK)
319 return rc;
320
321 return EOK;
322}
323
324/** Create callback session.
325 *
326 * Handle client request to create callback session.
327 *
328 * @param client UDP client
329 * @param icall_handle Async request call handle
330 * @param icall Async request data
331 */
332static void
333udp_callback_create_srv(udp_client_t *client, cap_call_handle_t icall_handle,
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) {
340 async_answer_0(icall_handle, ENOMEM);
341 return;
342 }
343
344 client->sess = sess;
345 async_answer_0(icall_handle, EOK);
346}
347
348/** Create association.
349 *
350 * Handle client request to create association.
351 *
352 * @param client UDP client
353 * @param icall_handle Async request call handle
354 * @param icall Async request data
355 */
356static void
357udp_assoc_create_srv(udp_client_t *client, cap_call_handle_t icall_handle,
358 ipc_call_t *icall)
359{
360 cap_call_handle_t chandle;
361 size_t size;
362 inet_ep2_t epp;
363 sysarg_t assoc_id;
364 errno_t rc;
365
366 log_msg(LOG_DEFAULT, LVL_DEBUG, "udp_assoc_create_srv()");
367
368 if (!async_data_write_receive(&chandle, &size)) {
369 async_answer_0(chandle, EREFUSED);
370 async_answer_0(icall_handle, EREFUSED);
371 return;
372 }
373
374 if (size != sizeof(inet_ep2_t)) {
375 async_answer_0(chandle, EINVAL);
376 async_answer_0(icall_handle, EINVAL);
377 return;
378 }
379
380 rc = async_data_write_finalize(chandle, &epp, size);
381 if (rc != EOK) {
382 async_answer_0(chandle, rc);
383 async_answer_0(icall_handle, rc);
384 return;
385 }
386
387 rc = udp_assoc_create_impl(client, &epp, &assoc_id);
388 if (rc != EOK) {
389 async_answer_0(icall_handle, rc);
390 return;
391 }
392
393 async_answer_1(icall_handle, EOK, assoc_id);
394}
395
396/** Destroy association.
397 *
398 * Handle client request to destroy association.
399 *
400 * @param client UDP client
401 * @param icall_handle Async request call handle
402 * @param icall Async request data
403 */
404static void
405udp_assoc_destroy_srv(udp_client_t *client, cap_call_handle_t icall_handle,
406 ipc_call_t *icall)
407{
408 sysarg_t assoc_id;
409 errno_t rc;
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);
415 async_answer_0(icall_handle, rc);
416}
417
418/** Set association with no local address.
419 *
420 * Handle client request to set no local address flag.
421 *
422 * @param client UDP client
423 * @param icall_handle Async request call handle
424 * @param icall Async request data
425 */
426static void
427udp_assoc_set_nolocal_srv(udp_client_t *client, cap_call_handle_t icall_handle,
428 ipc_call_t *icall)
429{
430 sysarg_t assoc_id;
431 errno_t rc;
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);
437 async_answer_0(icall_handle, rc);
438}
439
440/** Send message via association.
441 *
442 * Handle client request to send message.
443 *
444 * @param client UDP client
445 * @param icall_handle Async request call handle
446 * @param icall Async request data
447 */
448static void
449udp_assoc_send_msg_srv(udp_client_t *client, cap_call_handle_t icall_handle,
450 ipc_call_t *icall)
451{
452 cap_call_handle_t chandle;
453 size_t size;
454 inet_ep_t dest;
455 sysarg_t assoc_id;
456 void *data;
457 errno_t rc;
458
459 log_msg(LOG_DEFAULT, LVL_DEBUG, "udp_assoc_send_msg_srv()");
460
461 /* Receive dest */
462
463 if (!async_data_write_receive(&chandle, &size)) {
464 async_answer_0(chandle, EREFUSED);
465 async_answer_0(icall_handle, EREFUSED);
466 return;
467 }
468
469 if (size != sizeof(inet_ep_t)) {
470 async_answer_0(chandle, EINVAL);
471 async_answer_0(icall_handle, EINVAL);
472 return;
473 }
474
475 rc = async_data_write_finalize(chandle, &dest, size);
476 if (rc != EOK) {
477 async_answer_0(chandle, rc);
478 async_answer_0(icall_handle, rc);
479 return;
480 }
481
482 /* Receive message data */
483
484 if (!async_data_write_receive(&chandle, &size)) {
485 async_answer_0(chandle, EREFUSED);
486 async_answer_0(icall_handle, EREFUSED);
487 return;
488 }
489
490 if (size > MAX_MSG_SIZE) {
491 async_answer_0(chandle, EINVAL);
492 async_answer_0(icall_handle, EINVAL);
493 return;
494 }
495
496 data = malloc(size);
497 if (data == NULL) {
498 async_answer_0(chandle, ENOMEM);
499 async_answer_0(icall_handle, ENOMEM);
500 }
501
502 rc = async_data_write_finalize(chandle, data, size);
503 if (rc != EOK) {
504 async_answer_0(chandle, rc);
505 async_answer_0(icall_handle, rc);
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) {
514 async_answer_0(icall_handle, rc);
515 free(data);
516 return;
517 }
518
519 async_answer_0(icall_handle, EOK);
520 free(data);
521}
522
523/** Get next received message.
524 *
525 * @param client UDP Client
526 * @return Pointer to queue entry for next received message
527 */
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
539/** Get info on first received message.
540 *
541 * Handle client request to get information on received message.
542 *
543 * @param client UDP client
544 * @param icall_handle Async request call handle
545 * @param icall Async request data
546 */
547static void
548udp_rmsg_info_srv(udp_client_t *client, cap_call_handle_t icall_handle,
549 ipc_call_t *icall)
550{
551 cap_call_handle_t chandle;
552 size_t size;
553 udp_crcv_queue_entry_t *enext;
554 sysarg_t assoc_id;
555 errno_t rc;
556
557 log_msg(LOG_DEFAULT, LVL_DEBUG, "udp_rmsg_info_srv()");
558 enext = udp_rmsg_get_next(client);
559
560 if (!async_data_read_receive(&chandle, &size)) {
561 async_answer_0(chandle, EREFUSED);
562 async_answer_0(icall_handle, EREFUSED);
563 return;
564 }
565
566 if (enext == NULL) {
567 async_answer_0(chandle, ENOENT);
568 async_answer_0(icall_handle, ENOENT);
569 return;
570 }
571
572 rc = async_data_read_finalize(chandle, &enext->epp.remote,
573 max(size, (size_t)sizeof(inet_ep_t)));
574 if (rc != EOK) {
575 async_answer_0(icall_handle, rc);
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);
584 async_answer_2(icall_handle, EOK, assoc_id, size);
585}
586
587/** Read data from first received message.
588 *
589 * Handle client request to read data from first received message.
590 *
591 * @param client UDP client
592 * @param icall_handle Async request call handle
593 * @param icall Async request data
594 */
595static void
596udp_rmsg_read_srv(udp_client_t *client, cap_call_handle_t icall_handle,
597 ipc_call_t *icall)
598{
599 cap_call_handle_t chandle;
600 size_t msg_size;
601 udp_crcv_queue_entry_t *enext;
602 void *data;
603 size_t size;
604 size_t off;
605 errno_t rc;
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
612 if (!async_data_read_receive(&chandle, &size)) {
613 async_answer_0(chandle, EREFUSED);
614 async_answer_0(icall_handle, EREFUSED);
615 return;
616 }
617
618 if (enext == NULL) {
619 async_answer_0(chandle, ENOENT);
620 async_answer_0(icall_handle, ENOENT);
621 return;
622 }
623
624 data = enext->msg->data + off;
625 msg_size = enext->msg->data_size;
626
627 if (off > msg_size) {
628 async_answer_0(chandle, EINVAL);
629 async_answer_0(icall_handle, EINVAL);
630 return;
631 }
632
633 rc = async_data_read_finalize(chandle, data, min(msg_size - off, size));
634 if (rc != EOK) {
635 async_answer_0(icall_handle, rc);
636 return;
637 }
638
639 async_answer_0(icall_handle, EOK);
640 log_msg(LOG_DEFAULT, LVL_DEBUG, "udp_rmsg_read_srv(): OK");
641}
642
643/** Discard first received message.
644 *
645 * Handle client request to discard first received message, advancing
646 * to the next one.
647 *
648 * @param client UDP client
649 * @param icall_handle Async request call handle
650 * @param icall Async request data
651 */
652static void
653udp_rmsg_discard_srv(udp_client_t *client, cap_call_handle_t icall_handle,
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) {
662 log_msg(LOG_DEFAULT, LVL_DEBUG, "usg_rmsg_discard_srv: enext==NULL");
663 async_answer_0(icall_handle, ENOENT);
664 return;
665 }
666
667 list_remove(&enext->link);
668 udp_msg_delete(enext->msg);
669 free(enext);
670 async_answer_0(icall_handle, EOK);
671}
672
673/** Handle UDP client connection.
674 *
675 * @param icall_handle Connect call handle
676 * @param icall Connect call data
677 * @param arg Connection argument
678 */
679static void udp_client_conn(cap_call_handle_t icall_handle, ipc_call_t *icall,
680 void *arg)
681{
682 udp_client_t client;
683 unsigned long n;
684
685 /* Accept the connection */
686 async_answer_0(icall_handle, EOK);
687
688 log_msg(LOG_DEFAULT, LVL_DEBUG, "udp_client_conn()");
689
690 client.sess = NULL;
691 list_initialize(&client.cassoc);
692 list_initialize(&client.crcv_queue);
693
694 while (true) {
695 log_msg(LOG_DEFAULT, LVL_DEBUG, "udp_client_conn: wait req");
696 ipc_call_t call;
697 cap_call_handle_t chandle = async_get_call(&call);
698 sysarg_t method = IPC_GET_IMETHOD(call);
699
700 log_msg(LOG_DEFAULT, LVL_DEBUG, "udp_client_conn: method=%d",
701 (int)method);
702 if (!method) {
703 /* The other side has hung up */
704 async_answer_0(chandle, EOK);
705 break;
706 }
707
708 switch (method) {
709 case UDP_CALLBACK_CREATE:
710 udp_callback_create_srv(&client, chandle, &call);
711 break;
712 case UDP_ASSOC_CREATE:
713 udp_assoc_create_srv(&client, chandle, &call);
714 break;
715 case UDP_ASSOC_DESTROY:
716 udp_assoc_destroy_srv(&client, chandle, &call);
717 break;
718 case UDP_ASSOC_SET_NOLOCAL:
719 udp_assoc_set_nolocal_srv(&client, chandle, &call);
720 break;
721 case UDP_ASSOC_SEND_MSG:
722 udp_assoc_send_msg_srv(&client, chandle, &call);
723 break;
724 case UDP_RMSG_INFO:
725 udp_rmsg_info_srv(&client, chandle, &call);
726 break;
727 case UDP_RMSG_READ:
728 udp_rmsg_read_srv(&client, chandle, &call);
729 break;
730 case UDP_RMSG_DISCARD:
731 udp_rmsg_discard_srv(&client, chandle, &call);
732 break;
733 default:
734 async_answer_0(chandle, ENOTSUP);
735 break;
736 }
737 }
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: "
744 "Client with %lu active associations closed session.", n);
745 /* XXX Clean up */
746 }
747
748 /* XXX Clean up client receive queue */
749
750 if (client.sess != NULL)
751 async_hangup(client.sess);
752}
753
754/** Initialize UDP service.
755 *
756 * @return EOK on success or an error code.
757 */
758errno_t udp_service_init(void)
759{
760 errno_t rc;
761 service_id_t sid;
762
763 async_set_fallback_port_handler(udp_client_conn, NULL);
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.