source: mainline/uspace/srv/net/udp/sock.c@ f4a27304

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since f4a27304 was f4a27304, checked in by Martin Decky <martin@…>, 12 years ago

do not allocate the buffer on stack (thx Antonin Steinhauser)

  • Property mode set to 100644
File size: 20.1 KB
Line 
1/*
2 * Copyright (c) 2008 Lukas Mejdrech
3 * Copyright (c) 2012 Jiri Svoboda
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 *
10 * - Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * - Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * - The name of the author may not be used to endorse or promote products
16 * derived from this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */
29
30/** @addtogroup udp
31 * @{
32 */
33
34/**
35 * @file Socket provider
36 */
37
38#include <async.h>
39#include <byteorder.h>
40#include <errno.h>
41#include <inet/inet.h>
42#include <io/log.h>
43#include <ipc/services.h>
44#include <ipc/socket.h>
45#include <net/socket.h>
46#include <ns.h>
47
48#include "sock.h"
49#include "std.h"
50#include "udp_type.h"
51#include "ucall.h"
52
53/** Free ports pool start. */
54#define UDP_FREE_PORTS_START 1025
55
56/** Free ports pool end. */
57#define UDP_FREE_PORTS_END 65535
58
59static int last_used_port = UDP_FREE_PORTS_START - 1;
60static socket_ports_t gsock;
61
62static void udp_sock_connection(ipc_callid_t iid, ipc_call_t *icall, void *arg);
63static int udp_sock_recv_fibril(void *arg);
64
65int udp_sock_init(void)
66{
67 socket_ports_initialize(&gsock);
68
69 async_set_client_connection(udp_sock_connection);
70
71 int rc = service_register(SERVICE_UDP);
72 if (rc != EOK)
73 return EEXIST;
74
75 return EOK;
76}
77
78static void udp_free_sock_data(socket_core_t *sock_core)
79{
80 udp_sockdata_t *socket;
81
82 socket = (udp_sockdata_t *)sock_core->specific_data;
83 (void)socket;
84
85 /* XXX We need to force the receive fibril to quit */
86}
87
88static void udp_sock_notify_data(socket_core_t *sock_core)
89{
90 log_msg(LOG_DEFAULT, LVL_DEBUG, "udp_sock_notify_data(%d)", sock_core->socket_id);
91 async_exch_t *exch = async_exchange_begin(sock_core->sess);
92 async_msg_5(exch, NET_SOCKET_RECEIVED, (sysarg_t) sock_core->socket_id,
93 UDP_FRAGMENT_SIZE, 0, 0, 1);
94 async_exchange_end(exch);
95}
96
97static void udp_sock_socket(udp_client_t *client, ipc_callid_t callid, ipc_call_t call)
98{
99 udp_sockdata_t *sock;
100 socket_core_t *sock_core;
101 int sock_id;
102 int rc;
103 ipc_call_t answer;
104
105 log_msg(LOG_DEFAULT, LVL_DEBUG, "udp_sock_socket()");
106 sock = calloc(1, sizeof(udp_sockdata_t));
107 if (sock == NULL) {
108 async_answer_0(callid, ENOMEM);
109 return;
110 }
111
112 fibril_mutex_initialize(&sock->lock);
113 sock->client = client;
114
115 sock->recv_buffer_used = 0;
116 sock->recv_error = UDP_EOK;
117 fibril_mutex_initialize(&sock->recv_buffer_lock);
118 fibril_condvar_initialize(&sock->recv_buffer_cv);
119
120 rc = udp_uc_create(&sock->assoc);
121 if (rc != EOK) {
122 free(sock);
123 async_answer_0(callid, rc);
124 return;
125 }
126
127 sock->recv_fibril = fibril_create(udp_sock_recv_fibril, sock);
128 if (sock->recv_fibril == 0) {
129 udp_uc_destroy(sock->assoc);
130 free(sock);
131 async_answer_0(callid, ENOMEM);
132 return;
133 }
134
135 sock_id = SOCKET_GET_SOCKET_ID(call);
136 rc = socket_create(&client->sockets, client->sess, sock, &sock_id);
137 if (rc != EOK) {
138 fibril_destroy(sock->recv_fibril);
139 udp_uc_destroy(sock->assoc);
140 free(sock);
141 async_answer_0(callid, rc);
142 return;
143 }
144
145 fibril_add_ready(sock->recv_fibril);
146
147 sock_core = socket_cores_find(&client->sockets, sock_id);
148 assert(sock_core != NULL);
149 sock->sock_core = sock_core;
150
151 SOCKET_SET_SOCKET_ID(answer, sock_id);
152
153 SOCKET_SET_DATA_FRAGMENT_SIZE(answer, UDP_FRAGMENT_SIZE);
154 SOCKET_SET_HEADER_SIZE(answer, sizeof(udp_header_t));
155 async_answer_3(callid, EOK, IPC_GET_ARG1(answer),
156 IPC_GET_ARG2(answer), IPC_GET_ARG3(answer));
157}
158
159static void udp_sock_bind(udp_client_t *client, ipc_callid_t callid, ipc_call_t call)
160{
161 log_msg(LOG_DEFAULT, LVL_DEBUG, "udp_sock_bind()");
162 log_msg(LOG_DEFAULT, LVL_DEBUG, " - async_data_write_accept");
163
164 struct sockaddr_in6 *addr6 = NULL;
165 size_t addr_len;
166 int rc = async_data_write_accept((void **) &addr6, false, 0, 0, 0, &addr_len);
167 if (rc != EOK) {
168 async_answer_0(callid, rc);
169 return;
170 }
171
172 if ((addr_len != sizeof(struct sockaddr_in)) &&
173 (addr_len != sizeof(struct sockaddr_in6))) {
174 async_answer_0(callid, EINVAL);
175 goto out;
176 }
177
178 struct sockaddr_in *addr = (struct sockaddr_in *) addr6;
179
180 log_msg(LOG_DEFAULT, LVL_DEBUG, " - call socket_bind");
181
182 rc = socket_bind(&client->sockets, &gsock, SOCKET_GET_SOCKET_ID(call),
183 addr6, addr_len, UDP_FREE_PORTS_START, UDP_FREE_PORTS_END,
184 last_used_port);
185 if (rc != EOK) {
186 async_answer_0(callid, rc);
187 goto out;
188 }
189
190 log_msg(LOG_DEFAULT, LVL_DEBUG, " - call socket_cores_find");
191
192 socket_core_t *sock_core = socket_cores_find(&client->sockets,
193 SOCKET_GET_SOCKET_ID(call));
194 if (sock_core == NULL) {
195 async_answer_0(callid, ENOENT);
196 goto out;
197 }
198
199 udp_sockdata_t *socket =
200 (udp_sockdata_t *) sock_core->specific_data;
201
202 udp_sock_t fsocket;
203
204 fsocket.port = sock_core->port;
205
206 switch (addr->sin_family) {
207 case AF_INET:
208 inet_sockaddr_in_addr(addr, &fsocket.addr);
209 break;
210 case AF_INET6:
211 inet_sockaddr_in6_addr(addr6, &fsocket.addr);
212 break;
213 default:
214 async_answer_0(callid, EINVAL);
215 goto out;
216 }
217
218 udp_error_t urc = udp_uc_set_local(socket->assoc, &fsocket);
219
220 switch (urc) {
221 case UDP_EOK:
222 rc = EOK;
223 break;
224/* case TCP_ENOTEXIST:
225 rc = ENOTCONN;
226 break;
227 case TCP_ECLOSING:
228 rc = ENOTCONN;
229 break;
230 case TCP_ERESET:
231 rc = ECONNABORTED;
232 break;*/
233 default:
234 assert(false);
235 }
236
237 log_msg(LOG_DEFAULT, LVL_DEBUG, " - success");
238 async_answer_0(callid, rc);
239
240out:
241 if (addr6 != NULL)
242 free(addr6);
243}
244
245static void udp_sock_listen(udp_client_t *client, ipc_callid_t callid, ipc_call_t call)
246{
247 log_msg(LOG_DEFAULT, LVL_DEBUG, "udp_sock_listen()");
248 async_answer_0(callid, ENOTSUP);
249}
250
251static void udp_sock_connect(udp_client_t *client, ipc_callid_t callid, ipc_call_t call)
252{
253 log_msg(LOG_DEFAULT, LVL_DEBUG, "udp_sock_connect()");
254 async_answer_0(callid, ENOTSUP);
255}
256
257static void udp_sock_accept(udp_client_t *client, ipc_callid_t callid, ipc_call_t call)
258{
259 log_msg(LOG_DEFAULT, LVL_DEBUG, "udp_sock_accept()");
260 async_answer_0(callid, ENOTSUP);
261}
262
263static void udp_sock_sendto(udp_client_t *client, ipc_callid_t callid, ipc_call_t call)
264{
265 log_msg(LOG_DEFAULT, LVL_DEBUG, "udp_sock_send()");
266
267 uint8_t *buffer = calloc(UDP_FRAGMENT_SIZE, 1);
268 if (buffer == NULL) {
269 async_answer_0(callid, ENOMEM);
270 return;
271 }
272
273 struct sockaddr_in6 *addr6 = NULL;
274 struct sockaddr_in *addr;
275 udp_sock_t fsocket;
276 udp_sock_t *fsocket_ptr;
277
278 if (IPC_GET_IMETHOD(call) == NET_SOCKET_SENDTO) {
279 size_t addr_len;
280 int rc = async_data_write_accept((void **) &addr6, false,
281 0, 0, 0, &addr_len);
282 if (rc != EOK) {
283 async_answer_0(callid, rc);
284 goto out;
285 }
286
287 if ((addr_len != sizeof(struct sockaddr_in)) &&
288 (addr_len != sizeof(struct sockaddr_in6))) {
289 async_answer_0(callid, EINVAL);
290 goto out;
291 }
292
293 addr = (struct sockaddr_in *) addr6;
294
295 switch (addr->sin_family) {
296 case AF_INET:
297 inet_sockaddr_in_addr(addr, &fsocket.addr);
298 break;
299 case AF_INET6:
300 inet_sockaddr_in6_addr(addr6, &fsocket.addr);
301 break;
302 default:
303 async_answer_0(callid, EINVAL);
304 goto out;
305 }
306
307 fsocket.port = uint16_t_be2host(addr->sin_port);
308 fsocket_ptr = &fsocket;
309 } else
310 fsocket_ptr = NULL;
311
312 int socket_id = SOCKET_GET_SOCKET_ID(call);
313
314 SOCKET_GET_FLAGS(call);
315
316 socket_core_t *sock_core =
317 socket_cores_find(&client->sockets, socket_id);
318 if (sock_core == NULL) {
319 async_answer_0(callid, ENOTSOCK);
320 goto out;
321 }
322
323 udp_sockdata_t *socket =
324 (udp_sockdata_t *) sock_core->specific_data;
325
326 if (sock_core->port <= 0) {
327 /* Implicitly bind socket to port */
328 int rc = socket_bind_free_port(&gsock, sock_core,
329 UDP_FREE_PORTS_START, UDP_FREE_PORTS_END, last_used_port);
330 if (rc != EOK) {
331 async_answer_0(callid, rc);
332 goto out;
333 }
334
335 assert(sock_core->port > 0);
336
337 udp_error_t urc = udp_uc_set_local_port(socket->assoc,
338 sock_core->port);
339
340 if (urc != UDP_EOK) {
341 // TODO: better error handling
342 async_answer_0(callid, EINTR);
343 goto out;
344 }
345
346 last_used_port = sock_core->port;
347 }
348
349 fibril_mutex_lock(&socket->lock);
350
351 if (inet_addr_is_any(&socket->assoc->ident.local.addr)) {
352 /* Determine local IP address */
353 inet_addr_t loc_addr;
354 inet_addr_t rem_addr;
355
356 rem_addr = fsocket_ptr ? fsocket.addr :
357 socket->assoc->ident.foreign.addr;
358
359 int rc = inet_get_srcaddr(&rem_addr, 0, &loc_addr);
360 if (rc != EOK) {
361 fibril_mutex_unlock(&socket->lock);
362 async_answer_0(callid, rc);
363 log_msg(LOG_DEFAULT, LVL_DEBUG, "udp_sock_sendto: Failed to "
364 "determine local address.");
365 goto out;
366 }
367
368 socket->assoc->ident.local.addr = loc_addr;
369 }
370
371 assert(socket->assoc != NULL);
372
373 int fragments = SOCKET_GET_DATA_FRAGMENTS(call);
374 for (int index = 0; index < fragments; index++) {
375 ipc_callid_t wcallid;
376 size_t length;
377
378 if (!async_data_write_receive(&wcallid, &length)) {
379 fibril_mutex_unlock(&socket->lock);
380 async_answer_0(callid, EINVAL);
381 goto out;
382 }
383
384 if (length > UDP_FRAGMENT_SIZE)
385 length = UDP_FRAGMENT_SIZE;
386
387 int rc = async_data_write_finalize(wcallid, buffer, length);
388 if (rc != EOK) {
389 fibril_mutex_unlock(&socket->lock);
390 async_answer_0(callid, rc);
391 goto out;
392 }
393
394 udp_error_t urc =
395 udp_uc_send(socket->assoc, fsocket_ptr, buffer, length, 0);
396
397 switch (urc) {
398 case UDP_EOK:
399 rc = EOK;
400 break;
401 case UDP_ENORES:
402 rc = ENOMEM;
403 break;
404 case UDP_EUNSPEC:
405 rc = EINVAL;
406 break;
407 case UDP_ENOROUTE:
408 rc = EIO;
409 break;
410 default:
411 assert(false);
412 }
413
414 if (rc != EOK) {
415 fibril_mutex_unlock(&socket->lock);
416 async_answer_0(callid, rc);
417 goto out;
418 }
419 }
420
421 ipc_call_t answer;
422
423 IPC_SET_ARG1(answer, 0);
424 SOCKET_SET_DATA_FRAGMENT_SIZE(answer, UDP_FRAGMENT_SIZE);
425 async_answer_2(callid, EOK, IPC_GET_ARG1(answer),
426 IPC_GET_ARG2(answer));
427 fibril_mutex_unlock(&socket->lock);
428
429out:
430 if (addr6 != NULL)
431 free(addr6);
432
433 free(buffer);
434}
435
436static void udp_sock_recvfrom(udp_client_t *client, ipc_callid_t callid, ipc_call_t call)
437{
438 log_msg(LOG_DEFAULT, LVL_DEBUG, "%p: udp_sock_recv[from]()", client);
439
440 int socket_id = SOCKET_GET_SOCKET_ID(call);
441
442 socket_core_t *sock_core =
443 socket_cores_find(&client->sockets, socket_id);
444 if (sock_core == NULL) {
445 async_answer_0(callid, ENOTSOCK);
446 return;
447 }
448
449 udp_sockdata_t *socket =
450 (udp_sockdata_t *) sock_core->specific_data;
451
452 fibril_mutex_lock(&socket->lock);
453
454 if (socket->assoc == NULL) {
455 fibril_mutex_unlock(&socket->lock);
456 async_answer_0(callid, ENOTCONN);
457 return;
458 }
459
460 log_msg(LOG_DEFAULT, LVL_DEBUG, "udp_sock_recvfrom(): lock recv_buffer lock");
461
462 fibril_mutex_lock(&socket->recv_buffer_lock);
463
464 while ((socket->recv_buffer_used == 0) &&
465 (socket->recv_error == UDP_EOK)) {
466 log_msg(LOG_DEFAULT, LVL_DEBUG, "udp_sock_recvfrom(): wait for cv");
467 fibril_condvar_wait(&socket->recv_buffer_cv,
468 &socket->recv_buffer_lock);
469 }
470
471 log_msg(LOG_DEFAULT, LVL_DEBUG, "Got data in sock recv_buffer");
472
473 size_t data_len = socket->recv_buffer_used;
474 udp_error_t urc = socket->recv_error;
475
476 log_msg(LOG_DEFAULT, LVL_DEBUG, "**** recv data_len=%zu", data_len);
477
478 int rc;
479
480 switch (urc) {
481 case UDP_EOK:
482 rc = EOK;
483 break;
484/* case TCP_ENOTEXIST:
485 case TCP_ECLOSING:
486 rc = ENOTCONN;
487 break;
488 case TCP_ERESET:
489 rc = ECONNABORTED;
490 break;*/
491 default:
492 assert(false);
493 }
494
495 log_msg(LOG_DEFAULT, LVL_DEBUG, "**** udp_uc_receive -> %d", rc);
496
497 if (rc != EOK) {
498 fibril_mutex_unlock(&socket->recv_buffer_lock);
499 fibril_mutex_unlock(&socket->lock);
500 async_answer_0(callid, rc);
501 return;
502 }
503
504 ipc_callid_t rcallid;
505 size_t addr_size = 0;
506
507 if (IPC_GET_IMETHOD(call) == NET_SOCKET_RECVFROM) {
508 /* Fill address */
509 udp_sock_t *rsock = &socket->recv_fsock;
510 struct sockaddr_in addr;
511 struct sockaddr_in6 addr6;
512 size_t addr_length;
513
514 uint16_t addr_af = inet_addr_sockaddr_in(&rsock->addr, &addr,
515 &addr6);
516
517 switch (addr_af) {
518 case AF_INET:
519 addr.sin_port = host2uint16_t_be(rsock->port);
520
521 log_msg(LOG_DEFAULT, LVL_DEBUG, "addr read receive");
522 if (!async_data_read_receive(&rcallid, &addr_length)) {
523 fibril_mutex_unlock(&socket->recv_buffer_lock);
524 fibril_mutex_unlock(&socket->lock);
525 async_answer_0(callid, EINVAL);
526 return;
527 }
528
529 if (addr_length > sizeof(addr))
530 addr_length = sizeof(addr);
531
532 addr_size = sizeof(addr);
533
534 log_msg(LOG_DEFAULT, LVL_DEBUG, "addr read finalize");
535 rc = async_data_read_finalize(rcallid, &addr, addr_length);
536 if (rc != EOK) {
537 fibril_mutex_unlock(&socket->recv_buffer_lock);
538 fibril_mutex_unlock(&socket->lock);
539 async_answer_0(callid, EINVAL);
540 return;
541 }
542
543 break;
544 case AF_INET6:
545 addr6.sin6_port = host2uint16_t_be(rsock->port);
546
547 log_msg(LOG_DEFAULT, LVL_DEBUG, "addr6 read receive");
548 if (!async_data_read_receive(&rcallid, &addr_length)) {
549 fibril_mutex_unlock(&socket->recv_buffer_lock);
550 fibril_mutex_unlock(&socket->lock);
551 async_answer_0(callid, EINVAL);
552 return;
553 }
554
555 if (addr_length > sizeof(addr6))
556 addr_length = sizeof(addr6);
557
558 addr_size = sizeof(addr6);
559
560 log_msg(LOG_DEFAULT, LVL_DEBUG, "addr6 read finalize");
561 rc = async_data_read_finalize(rcallid, &addr6, addr_length);
562 if (rc != EOK) {
563 fibril_mutex_unlock(&socket->recv_buffer_lock);
564 fibril_mutex_unlock(&socket->lock);
565 async_answer_0(callid, EINVAL);
566 return;
567 }
568
569 break;
570 default:
571 fibril_mutex_unlock(&socket->recv_buffer_lock);
572 fibril_mutex_unlock(&socket->lock);
573 async_answer_0(callid, EINVAL);
574 return;
575 }
576 }
577
578 log_msg(LOG_DEFAULT, LVL_DEBUG, "data read receive");
579
580 size_t length;
581 if (!async_data_read_receive(&rcallid, &length)) {
582 fibril_mutex_unlock(&socket->recv_buffer_lock);
583 fibril_mutex_unlock(&socket->lock);
584 async_answer_0(callid, EINVAL);
585 return;
586 }
587
588 if (length > data_len)
589 length = data_len;
590
591 log_msg(LOG_DEFAULT, LVL_DEBUG, "data read finalize");
592
593 rc = async_data_read_finalize(rcallid, socket->recv_buffer, length);
594
595 if ((length < data_len) && (rc == EOK))
596 rc = EOVERFLOW;
597
598 log_msg(LOG_DEFAULT, LVL_DEBUG, "read_data_length <- %zu", length);
599
600 ipc_call_t answer;
601
602 IPC_SET_ARG2(answer, 0);
603 SOCKET_SET_READ_DATA_LENGTH(answer, length);
604 SOCKET_SET_ADDRESS_LENGTH(answer, addr_size);
605 async_answer_3(callid, EOK, IPC_GET_ARG1(answer),
606 IPC_GET_ARG2(answer), IPC_GET_ARG3(answer));
607
608 socket->recv_buffer_used = 0;
609
610 fibril_condvar_broadcast(&socket->recv_buffer_cv);
611 fibril_mutex_unlock(&socket->recv_buffer_lock);
612 fibril_mutex_unlock(&socket->lock);
613}
614
615static void udp_sock_close(udp_client_t *client, ipc_callid_t callid, ipc_call_t call)
616{
617 log_msg(LOG_DEFAULT, LVL_DEBUG, "tcp_sock_close()");
618 int socket_id = SOCKET_GET_SOCKET_ID(call);
619
620 log_msg(LOG_DEFAULT, LVL_DEBUG, "tcp_sock_close() - find core");
621 socket_core_t *sock_core =
622 socket_cores_find(&client->sockets, socket_id);
623 if (sock_core == NULL) {
624 log_msg(LOG_DEFAULT, LVL_DEBUG, "tcp_sock_close() - core not found");
625 async_answer_0(callid, ENOTSOCK);
626 return;
627 }
628
629 log_msg(LOG_DEFAULT, LVL_DEBUG, "tcp_sock_close() - spec data");
630 udp_sockdata_t *socket =
631 (udp_sockdata_t *) sock_core->specific_data;
632 log_msg(LOG_DEFAULT, LVL_DEBUG, "tcp_sock_close() - lock socket");
633 fibril_mutex_lock(&socket->lock);
634
635 log_msg(LOG_DEFAULT, LVL_DEBUG, "tcp_sock_close() - lock socket buffer");
636 fibril_mutex_lock(&socket->recv_buffer_lock);
637 log_msg(LOG_DEFAULT, LVL_DEBUG, "udp_sock_close - set socket->sock_core = NULL");
638 socket->sock_core = NULL;
639 fibril_mutex_unlock(&socket->recv_buffer_lock);
640
641 udp_uc_reset(socket->assoc);
642
643 int rc = socket_destroy(NULL, socket_id, &client->sockets, &gsock,
644 udp_free_sock_data);
645 if (rc != EOK) {
646 log_msg(LOG_DEFAULT, LVL_DEBUG, "udp_sock_close - socket_destroy failed");
647 fibril_mutex_unlock(&socket->lock);
648 async_answer_0(callid, rc);
649 return;
650 }
651
652 log_msg(LOG_DEFAULT, LVL_DEBUG, "udp_sock_close - broadcast recv_buffer_cv");
653 fibril_condvar_broadcast(&socket->recv_buffer_cv);
654
655 fibril_mutex_unlock(&socket->lock);
656 async_answer_0(callid, EOK);
657}
658
659static void udp_sock_getsockopt(udp_client_t *client, ipc_callid_t callid, ipc_call_t call)
660{
661 log_msg(LOG_DEFAULT, LVL_DEBUG, "udp_sock_getsockopt()");
662 async_answer_0(callid, ENOTSUP);
663}
664
665static void udp_sock_setsockopt(udp_client_t *client, ipc_callid_t callid, ipc_call_t call)
666{
667 log_msg(LOG_DEFAULT, LVL_DEBUG, "udp_sock_setsockopt()");
668 async_answer_0(callid, ENOTSUP);
669}
670
671static int udp_sock_recv_fibril(void *arg)
672{
673 udp_sockdata_t *sock = (udp_sockdata_t *)arg;
674 udp_error_t urc;
675 xflags_t xflags;
676 size_t rcvd;
677
678 log_msg(LOG_DEFAULT, LVL_DEBUG, "udp_sock_recv_fibril()");
679
680 fibril_mutex_lock(&sock->recv_buffer_lock);
681
682 while (true) {
683 log_msg(LOG_DEFAULT, LVL_DEBUG, "[] wait for rcv buffer empty()");
684 while ((sock->recv_buffer_used != 0) && (sock->sock_core != NULL)) {
685 fibril_condvar_wait(&sock->recv_buffer_cv,
686 &sock->recv_buffer_lock);
687 }
688
689 fibril_mutex_unlock(&sock->recv_buffer_lock);
690
691 log_msg(LOG_DEFAULT, LVL_DEBUG, "[] call udp_uc_receive()");
692 urc = udp_uc_receive(sock->assoc, sock->recv_buffer,
693 UDP_FRAGMENT_SIZE, &rcvd, &xflags, &sock->recv_fsock);
694 fibril_mutex_lock(&sock->recv_buffer_lock);
695 sock->recv_error = urc;
696
697 log_msg(LOG_DEFAULT, LVL_DEBUG, "[] udp_uc_receive -> %d", urc);
698
699 if (sock->sock_core != NULL)
700 udp_sock_notify_data(sock->sock_core);
701
702 if (urc != UDP_EOK) {
703 log_msg(LOG_DEFAULT, LVL_DEBUG, "[] urc != UDP_EOK, break");
704 fibril_condvar_broadcast(&sock->recv_buffer_cv);
705 fibril_mutex_unlock(&sock->recv_buffer_lock);
706 break;
707 }
708
709 log_msg(LOG_DEFAULT, LVL_DEBUG, "[] got data - broadcast recv_buffer_cv");
710
711 sock->recv_buffer_used = rcvd;
712 fibril_condvar_broadcast(&sock->recv_buffer_cv);
713 }
714
715 log_msg(LOG_DEFAULT, LVL_DEBUG, "udp_sock_recv_fibril() exited loop");
716 fibril_mutex_unlock(&sock->recv_buffer_lock);
717 udp_uc_destroy(sock->assoc);
718
719 log_msg(LOG_DEFAULT, LVL_DEBUG, "udp_sock_recv_fibril() terminated");
720
721 return 0;
722}
723
724static void udp_sock_connection(ipc_callid_t iid, ipc_call_t *icall, void *arg)
725{
726 ipc_callid_t callid;
727 ipc_call_t call;
728 udp_client_t client;
729
730 /* Accept the connection */
731 async_answer_0(iid, EOK);
732
733 client.sess = async_callback_receive(EXCHANGE_SERIALIZE);
734 socket_cores_initialize(&client.sockets);
735
736 while (true) {
737 log_msg(LOG_DEFAULT, LVL_DEBUG, "udp_sock_connection: wait");
738 callid = async_get_call(&call);
739 if (!IPC_GET_IMETHOD(call))
740 break;
741
742 log_msg(LOG_DEFAULT, LVL_DEBUG, "udp_sock_connection: METHOD=%d",
743 (int)IPC_GET_IMETHOD(call));
744
745 switch (IPC_GET_IMETHOD(call)) {
746 case NET_SOCKET:
747 udp_sock_socket(&client, callid, call);
748 break;
749 case NET_SOCKET_BIND:
750 udp_sock_bind(&client, callid, call);
751 break;
752 case NET_SOCKET_LISTEN:
753 udp_sock_listen(&client, callid, call);
754 break;
755 case NET_SOCKET_CONNECT:
756 udp_sock_connect(&client, callid, call);
757 break;
758 case NET_SOCKET_ACCEPT:
759 udp_sock_accept(&client, callid, call);
760 break;
761 case NET_SOCKET_SEND:
762 case NET_SOCKET_SENDTO:
763 udp_sock_sendto(&client, callid, call);
764 break;
765 case NET_SOCKET_RECV:
766 case NET_SOCKET_RECVFROM:
767 udp_sock_recvfrom(&client, callid, call);
768 break;
769 case NET_SOCKET_CLOSE:
770 udp_sock_close(&client, callid, call);
771 break;
772 case NET_SOCKET_GETSOCKOPT:
773 udp_sock_getsockopt(&client, callid, call);
774 break;
775 case NET_SOCKET_SETSOCKOPT:
776 udp_sock_setsockopt(&client, callid, call);
777 break;
778 default:
779 async_answer_0(callid, ENOTSUP);
780 break;
781 }
782 }
783
784 /* Clean up */
785 log_msg(LOG_DEFAULT, LVL_DEBUG, "udp_sock_connection: Clean up");
786 async_hangup(client.sess);
787 socket_cores_release(NULL, &client.sockets, &gsock, udp_free_sock_data);
788}
789
790/**
791 * @}
792 */
Note: See TracBrowser for help on using the repository browser.