source: mainline/uspace/srv/net/udp/service.c@ 1b9a853

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

Move UDP's client association to a separate module

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