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

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

use new network address infrastructure (towards IPv6 support)

  • Property mode set to 100644
File size: 18.6 KB
RevLine 
[66a272f8]1/*
[e33bceb]2 * Copyright (c) 2008 Lukas Mejdrech
[66a272f8]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
[e33bceb]38#include <async.h>
39#include <byteorder.h>
[66a272f8]40#include <errno.h>
[e33bceb]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>
[66a272f8]47
48#include "sock.h"
[e33bceb]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);
[32d19f7]63static int udp_sock_recv_fibril(void *arg);
[66a272f8]64
65int udp_sock_init(void)
66{
[e33bceb]67 socket_ports_initialize(&gsock);
[1038a9c]68
[e33bceb]69 async_set_client_connection(udp_sock_connection);
[1038a9c]70
71 int rc = service_register(SERVICE_UDP);
[e33bceb]72 if (rc != EOK)
73 return EEXIST;
[1038a9c]74
[66a272f8]75 return EOK;
76}
77
[e33bceb]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;
[32d19f7]83 (void)socket;
84
85 /* XXX We need to force the receive fibril to quit */
[e33bceb]86}
87
88static void udp_sock_notify_data(socket_core_t *sock_core)
89{
[a1a101d]90 log_msg(LOG_DEFAULT, LVL_DEBUG, "udp_sock_notify_data(%d)", sock_core->socket_id);
[e33bceb]91 async_exch_t *exch = async_exchange_begin(sock_core->sess);
[42fd4d2]92 async_msg_5(exch, NET_SOCKET_RECEIVED, (sysarg_t) sock_core->socket_id,
[32d19f7]93 UDP_FRAGMENT_SIZE, 0, 0, 1);
[e33bceb]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
[a1a101d]105 log_msg(LOG_DEFAULT, LVL_DEBUG, "udp_sock_socket()");
[db81577]106 sock = calloc(1, sizeof(udp_sockdata_t));
[e33bceb]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
[32d19f7]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
[e33bceb]120 rc = udp_uc_create(&sock->assoc);
121 if (rc != EOK) {
122 free(sock);
123 async_answer_0(callid, rc);
124 return;
125 }
126
[32d19f7]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
[e33bceb]135 sock_id = SOCKET_GET_SOCKET_ID(call);
136 rc = socket_create(&client->sockets, client->sess, sock, &sock_id);
137 if (rc != EOK) {
[32d19f7]138 fibril_destroy(sock->recv_fibril);
139 udp_uc_destroy(sock->assoc);
140 free(sock);
[e33bceb]141 async_answer_0(callid, rc);
142 return;
143 }
144
[32d19f7]145 fibril_add_ready(sock->recv_fibril);
146
[e33bceb]147 sock_core = socket_cores_find(&client->sockets, sock_id);
148 assert(sock_core != NULL);
149 sock->sock_core = sock_core;
[b1bd89ea]150
[e33bceb]151 SOCKET_SET_SOCKET_ID(answer, sock_id);
152
[32d19f7]153 SOCKET_SET_DATA_FRAGMENT_SIZE(answer, UDP_FRAGMENT_SIZE);
[e33bceb]154 SOCKET_SET_HEADER_SIZE(answer, sizeof(udp_header_t));
[b1bd89ea]155 async_answer_3(callid, EOK, IPC_GET_ARG1(answer),
156 IPC_GET_ARG2(answer), IPC_GET_ARG3(answer));
[e33bceb]157}
158
159static void udp_sock_bind(udp_client_t *client, ipc_callid_t callid, ipc_call_t call)
160{
161 int rc;
162 struct sockaddr_in *addr;
163 size_t addr_size;
164 socket_core_t *sock_core;
165 udp_sockdata_t *socket;
166 udp_sock_t fsock;
167 udp_error_t urc;
168
[a1a101d]169 log_msg(LOG_DEFAULT, LVL_DEBUG, "udp_sock_bind()");
170 log_msg(LOG_DEFAULT, LVL_DEBUG, " - async_data_write_accept");
[e33bceb]171
172 addr = NULL;
173
174 rc = async_data_write_accept((void **) &addr, false, 0, 0, 0, &addr_size);
175 if (rc != EOK) {
176 async_answer_0(callid, rc);
177 goto out;
178 }
[8fc8969]179
180 if (addr_size != sizeof(struct sockaddr_in)) {
181 async_answer_0(callid, EINVAL);
182 goto out;
183 }
184
[a1a101d]185 log_msg(LOG_DEFAULT, LVL_DEBUG, " - call socket_bind");
[e33bceb]186 rc = socket_bind(&client->sockets, &gsock, SOCKET_GET_SOCKET_ID(call),
187 addr, addr_size, UDP_FREE_PORTS_START, UDP_FREE_PORTS_END,
188 last_used_port);
189 if (rc != EOK) {
190 async_answer_0(callid, rc);
191 goto out;
192 }
[8fc8969]193
[a1a101d]194 log_msg(LOG_DEFAULT, LVL_DEBUG, " - call socket_cores_find");
[e33bceb]195 sock_core = socket_cores_find(&client->sockets, SOCKET_GET_SOCKET_ID(call));
196 if (sock_core == NULL) {
197 async_answer_0(callid, ENOENT);
198 goto out;
199 }
200
[19a4f73]201 socket = (udp_sockdata_t *) sock_core->specific_data;
202
[a2e3ee6]203 inet_addr_unpack(uint32_t_be2host(addr->sin_addr.s_addr),
[19a4f73]204 &fsock.addr);
[92b42442]205 fsock.port = sock_core->port;
[e33bceb]206 urc = udp_uc_set_local(socket->assoc, &fsock);
207
208 switch (urc) {
209 case UDP_EOK:
210 rc = EOK;
211 break;
212/* case TCP_ENOTEXIST:
213 rc = ENOTCONN;
214 break;
215 case TCP_ECLOSING:
216 rc = ENOTCONN;
217 break;
218 case TCP_ERESET:
219 rc = ECONNABORTED;
220 break;*/
221 default:
222 assert(false);
223 }
224
[a1a101d]225 log_msg(LOG_DEFAULT, LVL_DEBUG, " - success");
[e33bceb]226 async_answer_0(callid, rc);
227out:
228 if (addr != NULL)
229 free(addr);
230}
231
232static void udp_sock_listen(udp_client_t *client, ipc_callid_t callid, ipc_call_t call)
233{
[a1a101d]234 log_msg(LOG_DEFAULT, LVL_DEBUG, "udp_sock_listen()");
[e33bceb]235 async_answer_0(callid, ENOTSUP);
236}
237
238static void udp_sock_connect(udp_client_t *client, ipc_callid_t callid, ipc_call_t call)
239{
[a1a101d]240 log_msg(LOG_DEFAULT, LVL_DEBUG, "udp_sock_connect()");
[e33bceb]241 async_answer_0(callid, ENOTSUP);
242}
243
244static void udp_sock_accept(udp_client_t *client, ipc_callid_t callid, ipc_call_t call)
245{
[a1a101d]246 log_msg(LOG_DEFAULT, LVL_DEBUG, "udp_sock_accept()");
[e33bceb]247 async_answer_0(callid, ENOTSUP);
248}
249
250static void udp_sock_sendto(udp_client_t *client, ipc_callid_t callid, ipc_call_t call)
251{
[a1a101d]252 log_msg(LOG_DEFAULT, LVL_DEBUG, "udp_sock_send()");
[451481c8]253
254 struct sockaddr_in *addr = NULL;
255 udp_sock_t fsock;
256 udp_sock_t *fsock_ptr;
257
[e33bceb]258 if (IPC_GET_IMETHOD(call) == NET_SOCKET_SENDTO) {
[451481c8]259 size_t addr_size;
260 int rc = async_data_write_accept((void **) &addr, false,
[e33bceb]261 0, 0, 0, &addr_size);
262 if (rc != EOK) {
263 async_answer_0(callid, rc);
264 goto out;
265 }
[451481c8]266
[e33bceb]267 if (addr_size != sizeof(struct sockaddr_in)) {
268 async_answer_0(callid, EINVAL);
269 goto out;
270 }
[451481c8]271
[a2e3ee6]272 inet_addr_unpack(uint32_t_be2host(addr->sin_addr.s_addr),
[19a4f73]273 &fsock.addr);
[e33bceb]274 fsock.port = uint16_t_be2host(addr->sin_port);
[451481c8]275 fsock_ptr = &fsock;
276 } else
277 fsock_ptr = NULL;
278
279 int socket_id = SOCKET_GET_SOCKET_ID(call);
280
[e33bceb]281 SOCKET_GET_FLAGS(call);
[451481c8]282
283 socket_core_t *sock_core =
284 socket_cores_find(&client->sockets, socket_id);
[e33bceb]285 if (sock_core == NULL) {
286 async_answer_0(callid, ENOTSOCK);
287 goto out;
288 }
[451481c8]289
290 udp_sockdata_t *socket =
291 (udp_sockdata_t *) sock_core->specific_data;
292
[6b0b508]293 if (sock_core->port <= 0) {
[92b42442]294 /* Implicitly bind socket to port */
[451481c8]295 int rc = socket_bind_free_port(&gsock, sock_core,
296 UDP_FREE_PORTS_START, UDP_FREE_PORTS_END, last_used_port);
[e33bceb]297 if (rc != EOK) {
298 async_answer_0(callid, rc);
299 goto out;
300 }
[451481c8]301
302 assert(sock_core->port > 0);
[6b0b508]303
[451481c8]304 udp_error_t urc = udp_uc_set_local_port(socket->assoc,
305 sock_core->port);
306
307 if (urc != UDP_EOK) {
308 // TODO: better error handling
309 async_answer_0(callid, EINTR);
310 goto out;
311 }
[6b0b508]312
313 last_used_port = sock_core->port;
[e33bceb]314 }
[451481c8]315
[e33bceb]316 fibril_mutex_lock(&socket->lock);
[451481c8]317
[a2e3ee6]318 if (inet_addr_is_any(&socket->assoc->ident.local.addr)) {
[92b42442]319 /* Determine local IP address */
[a2e3ee6]320 inet_addr_t loc_addr;
321 inet_addr_t rem_addr;
[451481c8]322
[19a4f73]323 rem_addr = fsock_ptr ? fsock.addr :
324 socket->assoc->ident.foreign.addr;
[451481c8]325
[a2e3ee6]326 int rc = inet_get_srcaddr(&rem_addr, 0, &loc_addr);
[92b42442]327 if (rc != EOK) {
328 fibril_mutex_unlock(&socket->lock);
329 async_answer_0(callid, rc);
[a1a101d]330 log_msg(LOG_DEFAULT, LVL_DEBUG, "udp_sock_sendto: Failed to "
[92b42442]331 "determine local address.");
332 return;
333 }
[451481c8]334
[19a4f73]335 socket->assoc->ident.local.addr = loc_addr;
[92b42442]336 }
[451481c8]337
[e33bceb]338 assert(socket->assoc != NULL);
[451481c8]339
340 int fragments = SOCKET_GET_DATA_FRAGMENTS(call);
341 for (int index = 0; index < fragments; index++) {
342 ipc_callid_t wcallid;
343 size_t length;
344
[e33bceb]345 if (!async_data_write_receive(&wcallid, &length)) {
346 fibril_mutex_unlock(&socket->lock);
347 async_answer_0(callid, EINVAL);
348 goto out;
349 }
[451481c8]350
[32d19f7]351 if (length > UDP_FRAGMENT_SIZE)
352 length = UDP_FRAGMENT_SIZE;
[451481c8]353
354 uint8_t buffer[UDP_FRAGMENT_SIZE];
355 int rc = async_data_write_finalize(wcallid, buffer, length);
[e33bceb]356 if (rc != EOK) {
357 fibril_mutex_unlock(&socket->lock);
358 async_answer_0(callid, rc);
359 goto out;
360 }
[451481c8]361
362 udp_error_t urc =
363 udp_uc_send(socket->assoc, fsock_ptr, buffer, length, 0);
364
[e33bceb]365 switch (urc) {
366 case UDP_EOK:
367 rc = EOK;
368 break;
[08a6382]369 case UDP_ENORES:
[0ee053c1]370 rc = ENOMEM;
[e33bceb]371 break;
[08a6382]372 case UDP_EUNSPEC:
373 rc = EINVAL;
374 break;
375 case UDP_ENOROUTE:
376 rc = EIO;
[e33bceb]377 break;
378 default:
379 assert(false);
380 }
[451481c8]381
[e33bceb]382 if (rc != EOK) {
383 fibril_mutex_unlock(&socket->lock);
384 async_answer_0(callid, rc);
385 goto out;
386 }
387 }
[b1bd89ea]388
[451481c8]389 ipc_call_t answer;
390
[b1bd89ea]391 IPC_SET_ARG1(answer, 0);
[32d19f7]392 SOCKET_SET_DATA_FRAGMENT_SIZE(answer, UDP_FRAGMENT_SIZE);
[b1bd89ea]393 async_answer_2(callid, EOK, IPC_GET_ARG1(answer),
394 IPC_GET_ARG2(answer));
[e33bceb]395 fibril_mutex_unlock(&socket->lock);
[b1bd89ea]396
[e33bceb]397out:
398 if (addr != NULL)
399 free(addr);
400}
401
402static void udp_sock_recvfrom(udp_client_t *client, ipc_callid_t callid, ipc_call_t call)
403{
404 int socket_id;
405 int flags;
406 size_t addr_length, length;
407 socket_core_t *sock_core;
408 udp_sockdata_t *socket;
409 ipc_call_t answer;
410 ipc_callid_t rcallid;
411 size_t data_len;
412 udp_error_t urc;
[19a4f73]413 udp_sock_t *rsock;
[32d19f7]414 struct sockaddr_in addr;
[e33bceb]415 int rc;
416
[a1a101d]417 log_msg(LOG_DEFAULT, LVL_DEBUG, "%p: udp_sock_recv[from]()", client);
[e33bceb]418
419 socket_id = SOCKET_GET_SOCKET_ID(call);
420 flags = SOCKET_GET_FLAGS(call);
421
422 sock_core = socket_cores_find(&client->sockets, socket_id);
423 if (sock_core == NULL) {
424 async_answer_0(callid, ENOTSOCK);
425 return;
426 }
427
428 socket = (udp_sockdata_t *)sock_core->specific_data;
429 fibril_mutex_lock(&socket->lock);
430
431 if (socket->assoc == NULL) {
432 fibril_mutex_unlock(&socket->lock);
433 async_answer_0(callid, ENOTCONN);
434 return;
435 }
436
437 (void)flags;
438
[a1a101d]439 log_msg(LOG_DEFAULT, LVL_DEBUG, "udp_sock_recvfrom(): lock recv_buffer lock");
[32d19f7]440 fibril_mutex_lock(&socket->recv_buffer_lock);
441 while (socket->recv_buffer_used == 0 && socket->recv_error == UDP_EOK) {
[a1a101d]442 log_msg(LOG_DEFAULT, LVL_DEBUG, "udp_sock_recvfrom(): wait for cv");
[32d19f7]443 fibril_condvar_wait(&socket->recv_buffer_cv,
444 &socket->recv_buffer_lock);
445 }
446
[a1a101d]447 log_msg(LOG_DEFAULT, LVL_DEBUG, "Got data in sock recv_buffer");
[32d19f7]448
[19a4f73]449 rsock = &socket->recv_fsock;
[32d19f7]450 data_len = socket->recv_buffer_used;
451 urc = socket->recv_error;
452
[a1a101d]453 log_msg(LOG_DEFAULT, LVL_DEBUG, "**** recv data_len=%zu", data_len);
[e33bceb]454
455 switch (urc) {
456 case UDP_EOK:
457 rc = EOK;
458 break;
459/* case TCP_ENOTEXIST:
460 case TCP_ECLOSING:
461 rc = ENOTCONN;
462 break;
463 case TCP_ERESET:
464 rc = ECONNABORTED;
465 break;*/
466 default:
467 assert(false);
468 }
469
[a1a101d]470 log_msg(LOG_DEFAULT, LVL_DEBUG, "**** udp_uc_receive -> %d", rc);
[e33bceb]471 if (rc != EOK) {
[32d19f7]472 fibril_mutex_unlock(&socket->recv_buffer_lock);
[e33bceb]473 fibril_mutex_unlock(&socket->lock);
474 async_answer_0(callid, rc);
475 return;
476 }
477
478 if (IPC_GET_IMETHOD(call) == NET_SOCKET_RECVFROM) {
[19a4f73]479 /* Fill address */
480 uint32_t rsock_addr;
[a2e3ee6]481 int rc = inet_addr_pack(&rsock->addr, &rsock_addr);
[19a4f73]482 if (rc != EOK) {
483 fibril_mutex_unlock(&socket->recv_buffer_lock);
484 fibril_mutex_unlock(&socket->lock);
485 async_answer_0(callid, rc);
486 return;
487 }
488
[e33bceb]489 addr.sin_family = AF_INET;
[19a4f73]490 addr.sin_addr.s_addr = host2uint32_t_be(rsock_addr);
491 addr.sin_port = host2uint16_t_be(rsock->port);
[e33bceb]492
[a1a101d]493 log_msg(LOG_DEFAULT, LVL_DEBUG, "addr read receive");
[e33bceb]494 if (!async_data_read_receive(&rcallid, &addr_length)) {
[32d19f7]495 fibril_mutex_unlock(&socket->recv_buffer_lock);
[e33bceb]496 fibril_mutex_unlock(&socket->lock);
497 async_answer_0(callid, EINVAL);
498 return;
499 }
500
501 if (addr_length > sizeof(addr))
502 addr_length = sizeof(addr);
503
[a1a101d]504 log_msg(LOG_DEFAULT, LVL_DEBUG, "addr read finalize");
[e33bceb]505 rc = async_data_read_finalize(rcallid, &addr, addr_length);
506 if (rc != EOK) {
[32d19f7]507 fibril_mutex_unlock(&socket->recv_buffer_lock);
[e33bceb]508 fibril_mutex_unlock(&socket->lock);
509 async_answer_0(callid, EINVAL);
510 return;
511 }
512 }
513
[a1a101d]514 log_msg(LOG_DEFAULT, LVL_DEBUG, "data read receive");
[e33bceb]515 if (!async_data_read_receive(&rcallid, &length)) {
[32d19f7]516 fibril_mutex_unlock(&socket->recv_buffer_lock);
[e33bceb]517 fibril_mutex_unlock(&socket->lock);
518 async_answer_0(callid, EINVAL);
519 return;
520 }
521
522 if (length > data_len)
523 length = data_len;
524
[a1a101d]525 log_msg(LOG_DEFAULT, LVL_DEBUG, "data read finalize");
[32d19f7]526 rc = async_data_read_finalize(rcallid, socket->recv_buffer, length);
[e33bceb]527
528 if (length < data_len && rc == EOK)
529 rc = EOVERFLOW;
530
[a1a101d]531 log_msg(LOG_DEFAULT, LVL_DEBUG, "read_data_length <- %zu", length);
[b1bd89ea]532 IPC_SET_ARG2(answer, 0);
[e33bceb]533 SOCKET_SET_READ_DATA_LENGTH(answer, length);
[92b42442]534 SOCKET_SET_ADDRESS_LENGTH(answer, sizeof(addr));
[b1bd89ea]535 async_answer_3(callid, EOK, IPC_GET_ARG1(answer),
536 IPC_GET_ARG2(answer), IPC_GET_ARG3(answer));
[32d19f7]537
538 socket->recv_buffer_used = 0;
539
540 fibril_condvar_broadcast(&socket->recv_buffer_cv);
541 fibril_mutex_unlock(&socket->recv_buffer_lock);
[e33bceb]542 fibril_mutex_unlock(&socket->lock);
543}
544
545static void udp_sock_close(udp_client_t *client, ipc_callid_t callid, ipc_call_t call)
546{
[a1a101d]547 log_msg(LOG_DEFAULT, LVL_DEBUG, "tcp_sock_close()");
[42fd4d2]548 int socket_id = SOCKET_GET_SOCKET_ID(call);
[e33bceb]549
[ccb5165]550 log_msg(LOG_DEFAULT, LVL_DEBUG, "tcp_sock_close() - find core");
[42fd4d2]551 socket_core_t *sock_core =
552 socket_cores_find(&client->sockets, socket_id);
[e33bceb]553 if (sock_core == NULL) {
[ccb5165]554 log_msg(LOG_DEFAULT, LVL_DEBUG, "tcp_sock_close() - core not found");
[e33bceb]555 async_answer_0(callid, ENOTSOCK);
556 return;
557 }
558
[ccb5165]559 log_msg(LOG_DEFAULT, LVL_DEBUG, "tcp_sock_close() - spec data");
[42fd4d2]560 udp_sockdata_t *socket =
561 (udp_sockdata_t *) sock_core->specific_data;
[ccb5165]562 log_msg(LOG_DEFAULT, LVL_DEBUG, "tcp_sock_close() - lock socket");
[e33bceb]563 fibril_mutex_lock(&socket->lock);
564
[ccb5165]565 log_msg(LOG_DEFAULT, LVL_DEBUG, "tcp_sock_close() - lock socket buffer");
[141a20d]566 fibril_mutex_lock(&socket->recv_buffer_lock);
[a1e2df13]567 log_msg(LOG_DEFAULT, LVL_DEBUG, "udp_sock_close - set socket->sock_core = NULL");
[141a20d]568 socket->sock_core = NULL;
569 fibril_mutex_unlock(&socket->recv_buffer_lock);
570
571 udp_uc_reset(socket->assoc);
572
[42fd4d2]573 int rc = socket_destroy(NULL, socket_id, &client->sockets, &gsock,
[e33bceb]574 udp_free_sock_data);
575 if (rc != EOK) {
[a1e2df13]576 log_msg(LOG_DEFAULT, LVL_DEBUG, "udp_sock_close - socket_destroy failed");
[e33bceb]577 fibril_mutex_unlock(&socket->lock);
578 async_answer_0(callid, rc);
579 return;
580 }
581
[a1e2df13]582 log_msg(LOG_DEFAULT, LVL_DEBUG, "udp_sock_close - broadcast recv_buffer_cv");
[141a20d]583 fibril_condvar_broadcast(&socket->recv_buffer_cv);
584
[e33bceb]585 fibril_mutex_unlock(&socket->lock);
586 async_answer_0(callid, EOK);
587}
588
589static void udp_sock_getsockopt(udp_client_t *client, ipc_callid_t callid, ipc_call_t call)
590{
[a1a101d]591 log_msg(LOG_DEFAULT, LVL_DEBUG, "udp_sock_getsockopt()");
[e33bceb]592 async_answer_0(callid, ENOTSUP);
593}
594
595static void udp_sock_setsockopt(udp_client_t *client, ipc_callid_t callid, ipc_call_t call)
596{
[a1a101d]597 log_msg(LOG_DEFAULT, LVL_DEBUG, "udp_sock_setsockopt()");
[e33bceb]598 async_answer_0(callid, ENOTSUP);
599}
600
[32d19f7]601static int udp_sock_recv_fibril(void *arg)
602{
603 udp_sockdata_t *sock = (udp_sockdata_t *)arg;
604 udp_error_t urc;
605 xflags_t xflags;
606 size_t rcvd;
607
[a1a101d]608 log_msg(LOG_DEFAULT, LVL_DEBUG, "udp_sock_recv_fibril()");
[32d19f7]609
[141a20d]610 fibril_mutex_lock(&sock->recv_buffer_lock);
611
[32d19f7]612 while (true) {
[a1a101d]613 log_msg(LOG_DEFAULT, LVL_DEBUG, "[] wait for rcv buffer empty()");
[141a20d]614 while (sock->recv_buffer_used != 0 && sock->sock_core != NULL) {
[32d19f7]615 fibril_condvar_wait(&sock->recv_buffer_cv,
616 &sock->recv_buffer_lock);
617 }
[ccb5165]618
619 fibril_mutex_unlock(&sock->recv_buffer_lock);
620
[a1a101d]621 log_msg(LOG_DEFAULT, LVL_DEBUG, "[] call udp_uc_receive()");
[32d19f7]622 urc = udp_uc_receive(sock->assoc, sock->recv_buffer,
623 UDP_FRAGMENT_SIZE, &rcvd, &xflags, &sock->recv_fsock);
[ccb5165]624 fibril_mutex_lock(&sock->recv_buffer_lock);
[32d19f7]625 sock->recv_error = urc;
626
[a1e2df13]627 log_msg(LOG_DEFAULT, LVL_DEBUG, "[] udp_uc_receive -> %d", urc);
[141a20d]628
629 if (sock->sock_core != NULL)
630 udp_sock_notify_data(sock->sock_core);
[ccb5165]631
[32d19f7]632 if (urc != UDP_EOK) {
[a1e2df13]633 log_msg(LOG_DEFAULT, LVL_DEBUG, "[] urc != UDP_EOK, break");
[32d19f7]634 fibril_condvar_broadcast(&sock->recv_buffer_cv);
635 break;
636 }
[ccb5165]637
[a1a101d]638 log_msg(LOG_DEFAULT, LVL_DEBUG, "[] got data - broadcast recv_buffer_cv");
[ccb5165]639
[32d19f7]640 sock->recv_buffer_used = rcvd;
641 fibril_condvar_broadcast(&sock->recv_buffer_cv);
642 }
643
[a1e2df13]644 log_msg(LOG_DEFAULT, LVL_DEBUG, "udp_sock_recv_fibril() exited loop");
[141a20d]645 fibril_mutex_unlock(&sock->recv_buffer_lock);
[32d19f7]646 udp_uc_destroy(sock->assoc);
647
[a1e2df13]648 log_msg(LOG_DEFAULT, LVL_DEBUG, "udp_sock_recv_fibril() terminated");
[141a20d]649
[32d19f7]650 return 0;
651}
652
[e33bceb]653static void udp_sock_connection(ipc_callid_t iid, ipc_call_t *icall, void *arg)
654{
655 ipc_callid_t callid;
656 ipc_call_t call;
657 udp_client_t client;
658
659 /* Accept the connection */
660 async_answer_0(iid, EOK);
661
662 client.sess = async_callback_receive(EXCHANGE_SERIALIZE);
663 socket_cores_initialize(&client.sockets);
664
665 while (true) {
[a1a101d]666 log_msg(LOG_DEFAULT, LVL_DEBUG, "udp_sock_connection: wait");
[e33bceb]667 callid = async_get_call(&call);
668 if (!IPC_GET_IMETHOD(call))
669 break;
670
[a1a101d]671 log_msg(LOG_DEFAULT, LVL_DEBUG, "udp_sock_connection: METHOD=%d",
[e33bceb]672 (int)IPC_GET_IMETHOD(call));
673
674 switch (IPC_GET_IMETHOD(call)) {
675 case NET_SOCKET:
676 udp_sock_socket(&client, callid, call);
677 break;
678 case NET_SOCKET_BIND:
679 udp_sock_bind(&client, callid, call);
680 break;
681 case NET_SOCKET_LISTEN:
682 udp_sock_listen(&client, callid, call);
683 break;
684 case NET_SOCKET_CONNECT:
685 udp_sock_connect(&client, callid, call);
686 break;
687 case NET_SOCKET_ACCEPT:
688 udp_sock_accept(&client, callid, call);
689 break;
690 case NET_SOCKET_SEND:
691 case NET_SOCKET_SENDTO:
692 udp_sock_sendto(&client, callid, call);
693 break;
694 case NET_SOCKET_RECV:
695 case NET_SOCKET_RECVFROM:
696 udp_sock_recvfrom(&client, callid, call);
697 break;
698 case NET_SOCKET_CLOSE:
699 udp_sock_close(&client, callid, call);
700 break;
701 case NET_SOCKET_GETSOCKOPT:
702 udp_sock_getsockopt(&client, callid, call);
703 break;
704 case NET_SOCKET_SETSOCKOPT:
705 udp_sock_setsockopt(&client, callid, call);
706 break;
707 default:
708 async_answer_0(callid, ENOTSUP);
709 break;
710 }
711 }
[0d520a2]712
713 /* Clean up */
[a1a101d]714 log_msg(LOG_DEFAULT, LVL_DEBUG, "udp_sock_connection: Clean up");
[0d520a2]715 async_hangup(client.sess);
716 socket_cores_release(NULL, &client.sockets, &gsock, udp_free_sock_data);
[e33bceb]717}
718
[66a272f8]719/**
720 * @}
721 */
Note: See TracBrowser for help on using the repository browser.