source: mainline/uspace/srv/net/tl/tcp/sock.c@ 5f9ecd3

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 5f9ecd3 was 3aa2642a, checked in by Jiri Svoboda <jiri@…>, 14 years ago

Allow accepting connection from arbitray foreign address, port.

  • Property mode set to 100644
File size: 16.2 KB
RevLine 
[04cd242]1/*
2 * Copyright (c) 2008 Lukas Mejdrech
3 * Copyright (c) 2011 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 tcp
31 * @{
32 */
33
34/**
35 * @file Socket provider
36 */
37
38#include <async.h>
39#include <errno.h>
40#include <io/log.h>
41#include <ipc/socket.h>
42#include <net/modules.h>
[a4ee3ab2]43#include <net/socket.h>
[04cd242]44
45#include "sock.h"
46#include "std.h"
47#include "tcp.h"
48#include "tcp_type.h"
49#include "ucall.h"
50
51#define FRAGMENT_SIZE 1024
52
53/** Free ports pool start. */
54#define TCP_FREE_PORTS_START 1025
55
56/** Free ports pool end. */
57#define TCP_FREE_PORTS_END 65535
58
[a4ee3ab2]59static int last_used_port = TCP_FREE_PORTS_START - 1;
[04cd242]60static socket_ports_t gsock;
61
[a4ee3ab2]62void tcp_sock_init(void)
63{
64 socket_ports_initialize(&gsock);
65}
66
[04cd242]67static void tcp_free_sock_data(socket_core_t *sock_core)
68{
69 tcp_sockdata_t *socket;
70
71 socket = (tcp_sockdata_t *)sock_core->specific_data;
72 (void)socket;
73}
74
75static void tcp_sock_notify_data(socket_core_t *sock_core)
76{
[a4ee3ab2]77 log_msg(LVL_DEBUG, "tcp_sock_notify_data(%d)", sock_core->socket_id);
[04cd242]78 async_exch_t *exch = async_exchange_begin(sock_core->sess);
79 async_msg_5(exch, NET_SOCKET_RECEIVED, (sysarg_t)sock_core->socket_id,
80 FRAGMENT_SIZE, 0, 0, 1);
81 async_exchange_end(exch);
82}
83
[a4ee3ab2]84static void tcp_sock_notify_aconn(socket_core_t *lsock_core)
85{
86 log_msg(LVL_DEBUG, "tcp_sock_notify_aconn(%d)", lsock_core->socket_id);
87 async_exch_t *exch = async_exchange_begin(lsock_core->sess);
88 async_msg_5(exch, NET_SOCKET_ACCEPTED, (sysarg_t)lsock_core->socket_id,
89 FRAGMENT_SIZE, 0, 0, 0);
90 async_exchange_end(exch);
91}
92
[04cd242]93static void tcp_sock_socket(tcp_client_t *client, ipc_callid_t callid, ipc_call_t call)
94{
95 tcp_sockdata_t *sock;
96 int sock_id;
97 int rc;
98 ipc_call_t answer;
99
100 log_msg(LVL_DEBUG, "tcp_sock_socket()");
101 sock = calloc(sizeof(tcp_sockdata_t), 1);
102 if (sock == NULL) {
103 async_answer_0(callid, ENOMEM);
104 return;
105 }
106
107 sock->client = client;
108
109 sock_id = SOCKET_GET_SOCKET_ID(call);
110 rc = socket_create(&client->sockets, client->sess, sock, &sock_id);
111 if (rc != EOK) {
112 async_answer_0(callid, rc);
113 return;
114 }
115
116 refresh_answer(&answer, NULL);
117 SOCKET_SET_SOCKET_ID(answer, sock_id);
118
119 SOCKET_SET_DATA_FRAGMENT_SIZE(answer, FRAGMENT_SIZE);
120 SOCKET_SET_HEADER_SIZE(answer, sizeof(tcp_header_t));
121 answer_call(callid, EOK, &answer, 3);
122}
123
124static void tcp_sock_bind(tcp_client_t *client, ipc_callid_t callid, ipc_call_t call)
125{
126 int rc;
127 struct sockaddr *addr;
128 size_t addr_len;
129 socket_core_t *sock_core;
130 tcp_sockdata_t *socket;
131
132 log_msg(LVL_DEBUG, "tcp_sock_bind()");
[a4ee3ab2]133 log_msg(LVL_DEBUG, " - async_data_write_accept");
[04cd242]134 rc = async_data_write_accept((void **) &addr, false, 0, 0, 0, &addr_len);
135 if (rc != EOK) {
136 async_answer_0(callid, rc);
137 return;
138 }
139
[a4ee3ab2]140 log_msg(LVL_DEBUG, " - call socket_bind");
[04cd242]141 rc = socket_bind(&client->sockets, &gsock, SOCKET_GET_SOCKET_ID(call),
142 addr, addr_len, TCP_FREE_PORTS_START, TCP_FREE_PORTS_END,
143 last_used_port);
144 if (rc != EOK) {
145 async_answer_0(callid, rc);
146 return;
147 }
148
[a4ee3ab2]149 log_msg(LVL_DEBUG, " - call socket_cores_find");
[04cd242]150 sock_core = socket_cores_find(&client->sockets, SOCKET_GET_SOCKET_ID(call));
151 if (sock_core != NULL) {
152 socket = (tcp_sockdata_t *)sock_core->specific_data;
153 /* XXX Anything to do? */
154 (void) socket;
155 }
156
[a4ee3ab2]157 log_msg(LVL_DEBUG, " - success");
158 async_answer_0(callid, EOK);
[04cd242]159}
160
161static void tcp_sock_listen(tcp_client_t *client, ipc_callid_t callid, ipc_call_t call)
162{
163 int socket_id;
164 int backlog;
165 socket_core_t *sock_core;
166 tcp_sockdata_t *socket;
167
168 log_msg(LVL_DEBUG, "tcp_sock_listen()");
169
170 socket_id = SOCKET_GET_SOCKET_ID(call);
171 backlog = SOCKET_GET_BACKLOG(call);
172
173 if (backlog < 0) {
174 async_answer_0(callid, EINVAL);
175 return;
176 }
177
178 sock_core = socket_cores_find(&client->sockets, socket_id);
179 if (sock_core == NULL) {
180 async_answer_0(callid, ENOTSOCK);
181 return;
182 }
183
184 socket = (tcp_sockdata_t *)sock_core->specific_data;
[a4ee3ab2]185
186 /*
187 * XXX We do not do anything and defer action to accept().
188 * This is a slight difference in semantics, but most servers
189 * would just listen() and immediately accept() in a loop.
190 *
191 * The only difference is that there is a window between
192 * listen() and accept() or two accept()s where we refuse
193 * connections.
194 */
[04cd242]195 (void)backlog;
196 (void)socket;
197
[a4ee3ab2]198 async_answer_0(callid, EOK);
199 log_msg(LVL_DEBUG, "tcp_sock_listen(): notify data\n");
200 /* Push one accept notification to client's queue */
201 tcp_sock_notify_aconn(sock_core);
[04cd242]202}
203
204static void tcp_sock_connect(tcp_client_t *client, ipc_callid_t callid, ipc_call_t call)
205{
206 int rc;
207 struct sockaddr_in *addr;
208 int socket_id;
209 size_t addr_len;
210 socket_core_t *sock_core;
211 tcp_sockdata_t *socket;
212 tcp_error_t trc;
213 tcp_sock_t fsocket;
214 uint16_t lport;
215
216 log_msg(LVL_DEBUG, "tcp_sock_connect()");
217
218 rc = async_data_write_accept((void **) &addr, false, 0, 0, 0, &addr_len);
219 if (rc != EOK || addr_len != sizeof(struct sockaddr_in)) {
220 async_answer_0(callid, rc);
221 return;
222 }
223
224 socket_id = SOCKET_GET_SOCKET_ID(call);
225
226 sock_core = socket_cores_find(&client->sockets, socket_id);
227 if (sock_core == NULL) {
228 async_answer_0(callid, ENOTSOCK);
229 return;
230 }
231
232 socket = (tcp_sockdata_t *)sock_core->specific_data;
[a4ee3ab2]233 if (sock_core->port <= 0) {
234 rc = socket_bind_free_port(&gsock, sock_core,
235 TCP_FREE_PORTS_START, TCP_FREE_PORTS_END,
236 last_used_port);
237 if (rc != EOK) {
238 async_answer_0(callid, rc);
239 return;
240 }
241
242 last_used_port = sock_core->port;
243 }
[04cd242]244
[a4ee3ab2]245 lport = sock_core->port;
[04cd242]246 fsocket.addr.ipv4 = uint32_t_be2host(addr->sin_addr.s_addr);
247 fsocket.port = uint16_t_be2host(addr->sin_port);
248
249 trc = tcp_uc_open(lport, &fsocket, ap_active, &socket->conn);
[704586fb]250
251 if (socket->conn != NULL)
252 socket->conn->name = (char *)"C";
[04cd242]253
254 switch (trc) {
255 case TCP_EOK:
256 rc = EOK;
257 break;
258 case TCP_ERESET:
259 rc = ECONNREFUSED;
260 break;
261 default:
262 assert(false);
263 }
264
265 async_answer_0(callid, rc);
[8fcf74f]266
267 /* Push one fragment notification to client's queue */
268 tcp_sock_notify_data(sock_core);
[23fe06c]269 log_msg(LVL_DEBUG, "tcp_sock_connect(): notify conn\n");
[04cd242]270}
271
272static void tcp_sock_accept(tcp_client_t *client, ipc_callid_t callid, ipc_call_t call)
273{
274 ipc_call_t answer;
275 int socket_id;
[a4ee3ab2]276 int asock_id;
[04cd242]277 socket_core_t *sock_core;
[a4ee3ab2]278 socket_core_t *asock_core;
[04cd242]279 tcp_sockdata_t *socket;
[a4ee3ab2]280 tcp_sockdata_t *asocket;
281 tcp_error_t trc;
282 tcp_sock_t fsocket;
283 tcp_conn_t *conn;
284 int rc;
[04cd242]285
286 log_msg(LVL_DEBUG, "tcp_sock_accept()");
287
288 socket_id = SOCKET_GET_SOCKET_ID(call);
[a4ee3ab2]289 asock_id = SOCKET_GET_NEW_SOCKET_ID(call);
[04cd242]290
291 sock_core = socket_cores_find(&client->sockets, socket_id);
292 if (sock_core == NULL) {
293 async_answer_0(callid, ENOTSOCK);
294 return;
295 }
296
297 socket = (tcp_sockdata_t *)sock_core->specific_data;
[a4ee3ab2]298
299 log_msg(LVL_DEBUG, " - verify socket->conn");
300 if (socket->conn != NULL) {
301 async_answer_0(callid, EINVAL);
302 return;
303 }
304
305 log_msg(LVL_DEBUG, " - open connection");
306
[3aa2642a]307 fsocket.addr.ipv4 = TCP_IPV4_ANY;
308 fsocket.port = TCP_PORT_ANY;
[a4ee3ab2]309
310 trc = tcp_uc_open(sock_core->port, &fsocket, ap_passive, &conn);
[704586fb]311 if (conn != NULL)
312 conn->name = (char *)"S";
[a4ee3ab2]313
314 log_msg(LVL_DEBUG, " - decode TCP return code");
315
316 switch (trc) {
317 case TCP_EOK:
318 rc = EOK;
319 break;
320 case TCP_ERESET:
321 rc = ECONNABORTED;
322 break;
323 default:
324 assert(false);
325 }
326
327 log_msg(LVL_DEBUG, " - check TCP return code");
328 if (rc != EOK) {
329 async_answer_0(callid, rc);
330 return;
331 }
332
333 log_msg(LVL_DEBUG, "tcp_sock_accept(): allocate asocket\n");
334 asocket = calloc(sizeof(tcp_sockdata_t), 1);
335 if (asocket == NULL) {
336 async_answer_0(callid, ENOMEM);
337 return;
338 }
339
340 asocket->client = client;
341 asocket->conn = conn;
342 log_msg(LVL_DEBUG, "tcp_sock_accept():create asocket\n");
343
344 rc = socket_create(&client->sockets, client->sess, asocket, &asock_id);
345 if (rc != EOK) {
346 async_answer_0(callid, rc);
347 return;
348 }
349 log_msg(LVL_DEBUG, "tcp_sock_accept(): find acore\n");
350
351 asock_core = socket_cores_find(&client->sockets, asock_id);
352 assert(asock_core != NULL);
353
[04cd242]354 refresh_answer(&answer, NULL);
355
[a4ee3ab2]356 SOCKET_SET_DATA_FRAGMENT_SIZE(answer, FRAGMENT_SIZE);
357 SOCKET_SET_SOCKET_ID(answer, asock_id);
358 SOCKET_SET_ADDRESS_LENGTH(answer, sizeof(struct sockaddr_in));
359
360 answer_call(callid, asock_core->socket_id, &answer, 3);
361
362 /* Push one accept notification to client's queue */
363 tcp_sock_notify_aconn(sock_core);
364
365 /* Push one fragment notification to client's queue */
366 tcp_sock_notify_data(asock_core);
[23fe06c]367 log_msg(LVL_DEBUG, "tcp_sock_accept(): notify aconn\n");
[04cd242]368}
369
370static void tcp_sock_send(tcp_client_t *client, ipc_callid_t callid, ipc_call_t call)
371{
372 int socket_id;
373 int fragments;
374 int index;
375 socket_core_t *sock_core;
376 tcp_sockdata_t *socket;
377 ipc_call_t answer;
378 ipc_callid_t wcallid;
379 size_t length;
380 uint8_t buffer[FRAGMENT_SIZE];
381 tcp_error_t trc;
382 int rc;
383
[a4ee3ab2]384 log_msg(LVL_DEBUG, "tcp_sock_send()");
[04cd242]385 socket_id = SOCKET_GET_SOCKET_ID(call);
386 fragments = SOCKET_GET_DATA_FRAGMENTS(call);
387 SOCKET_GET_FLAGS(call);
388
389 sock_core = socket_cores_find(&client->sockets, socket_id);
390 if (sock_core == NULL) {
391 async_answer_0(callid, ENOTSOCK);
392 return;
393 }
394
395 socket = (tcp_sockdata_t *)sock_core->specific_data;
396 if (socket->conn == NULL) {
397 async_answer_0(callid, ENOTCONN);
398 return;
399 }
400
401 for (index = 0; index < fragments; index++) {
402 if (!async_data_write_receive(&wcallid, &length)) {
403 async_answer_0(callid, EINVAL);
404 return;
405 }
406
407 if (length > FRAGMENT_SIZE)
408 length = FRAGMENT_SIZE;
409
410 rc = async_data_write_finalize(wcallid, buffer, length);
411 if (rc != EOK) {
412 async_answer_0(callid, rc);
413 return;
414 }
415
416 trc = tcp_uc_send(socket->conn, buffer, length, 0);
417
418 switch (trc) {
419 case TCP_EOK:
420 rc = EOK;
421 break;
422 case TCP_ENOTEXIST:
423 rc = ENOTCONN;
424 break;
425 case TCP_ECLOSING:
426 rc = ENOTCONN;
427 break;
428 default:
429 assert(false);
430 }
431
432 if (rc != EOK) {
433 async_answer_0(callid, rc);
434 return;
435 }
436 }
437
438 refresh_answer(&answer, NULL);
439 SOCKET_SET_DATA_FRAGMENT_SIZE(answer, FRAGMENT_SIZE);
440 answer_call(callid, EOK, &answer, 2);
441}
442
443static void tcp_sock_sendto(tcp_client_t *client, ipc_callid_t callid, ipc_call_t call)
444{
445 log_msg(LVL_DEBUG, "tcp_sock_sendto()");
446 async_answer_0(callid, ENOTSUP);
447}
448
[a4ee3ab2]449static void tcp_sock_recvfrom(tcp_client_t *client, ipc_callid_t callid, ipc_call_t call)
[04cd242]450{
451 int socket_id;
452 int flags;
[a4ee3ab2]453 size_t addr_length, length;
[04cd242]454 socket_core_t *sock_core;
455 tcp_sockdata_t *socket;
456 ipc_call_t answer;
457 ipc_callid_t rcallid;
458 uint8_t buffer[FRAGMENT_SIZE];
459 size_t data_len;
460 xflags_t xflags;
461 tcp_error_t trc;
[a4ee3ab2]462 struct sockaddr_in addr;
463 tcp_sock_t *rsock;
[04cd242]464 int rc;
465
[23fe06c]466 log_msg(LVL_DEBUG, "%p: tcp_sock_recv[from]()", client);
[04cd242]467
468 socket_id = SOCKET_GET_SOCKET_ID(call);
469 flags = SOCKET_GET_FLAGS(call);
470
471 sock_core = socket_cores_find(&client->sockets, socket_id);
472 if (sock_core == NULL) {
473 async_answer_0(callid, ENOTSOCK);
474 return;
475 }
476
477 socket = (tcp_sockdata_t *)sock_core->specific_data;
[a4ee3ab2]478 if (socket->conn == NULL) {
479 async_answer_0(callid, ENOTCONN);
480 return;
481 }
[04cd242]482
483 (void)flags;
484
485 trc = tcp_uc_receive(socket->conn, buffer, FRAGMENT_SIZE, &data_len,
486 &xflags);
[a4ee3ab2]487 log_msg(LVL_DEBUG, "**** tcp_uc_receive done");
[04cd242]488
489 switch (trc) {
490 case TCP_EOK:
491 rc = EOK;
492 break;
493 case TCP_ENOTEXIST:
494 case TCP_ECLOSING:
495 rc = ENOTCONN;
496 break;
497 default:
498 assert(false);
499 }
500
[a4ee3ab2]501 log_msg(LVL_DEBUG, "**** tcp_uc_receive -> %d", rc);
[04cd242]502 if (rc != EOK) {
503 async_answer_0(callid, rc);
504 return;
505 }
506
[a4ee3ab2]507 if (IPC_GET_IMETHOD(call) == NET_SOCKET_RECVFROM) {
508 /* Fill addr */
509 rsock = &socket->conn->ident.foreign;
510 addr.sin_family = AF_INET;
511 addr.sin_addr.s_addr = host2uint32_t_be(rsock->addr.ipv4);
512 addr.sin_port = host2uint16_t_be(rsock->port);
513
514 log_msg(LVL_DEBUG, "addr read receive");
515 if (!async_data_read_receive(&rcallid, &addr_length)) {
516 async_answer_0(callid, EINVAL);
517 return;
518 }
519
520 if (addr_length > sizeof(addr))
521 addr_length = sizeof(addr);
522
523 log_msg(LVL_DEBUG, "addr read finalize");
524 rc = async_data_read_finalize(rcallid, &addr, addr_length);
525 if (rc != EOK) {
526 async_answer_0(callid, EINVAL);
527 return;
528 }
529 }
530
531 log_msg(LVL_DEBUG, "data read receive");
[04cd242]532 if (!async_data_read_receive(&rcallid, &length)) {
533 async_answer_0(callid, EINVAL);
534 return;
535 }
536
[a4ee3ab2]537 if (length > data_len)
[04cd242]538 length = data_len;
539
[a4ee3ab2]540 log_msg(LVL_DEBUG, "data read finalize");
[04cd242]541 rc = async_data_read_finalize(rcallid, buffer, length);
[a4ee3ab2]542
543 if (length < data_len && rc == EOK)
544 rc = EOVERFLOW;
[04cd242]545
546 SOCKET_SET_READ_DATA_LENGTH(answer, length);
547 answer_call(callid, EOK, &answer, 1);
548
549 /* Push one fragment notification to client's queue */
550 tcp_sock_notify_data(sock_core);
551}
552
553static void tcp_sock_close(tcp_client_t *client, ipc_callid_t callid, ipc_call_t call)
554{
555 int socket_id;
556 socket_core_t *sock_core;
557 tcp_sockdata_t *socket;
[b0d82d1]558 tcp_error_t trc;
[04cd242]559 int rc;
[b0d82d1]560 uint8_t buffer[FRAGMENT_SIZE];
561 size_t data_len;
562 xflags_t xflags;
[04cd242]563
564 log_msg(LVL_DEBUG, "tcp_sock_close()");
565 socket_id = SOCKET_GET_SOCKET_ID(call);
566
567 sock_core = socket_cores_find(&client->sockets, socket_id);
568 if (sock_core == NULL) {
569 async_answer_0(callid, ENOTSOCK);
570 return;
571 }
572
573 socket = (tcp_sockdata_t *)sock_core->specific_data;
[b0d82d1]574 rc = tcp_uc_close(socket->conn);
575 if (rc != EOK) {
576 async_answer_0(callid, rc);
577 return;
578 }
579
580 /* Drain incoming data. This should really be done in the background. */
581 do {
582 trc = tcp_uc_receive(socket->conn, buffer, FRAGMENT_SIZE,
583 &data_len, &xflags);
584 } while (trc == TCP_EOK);
[04cd242]585
586 rc = socket_destroy(net_sess, socket_id, &client->sockets, &gsock,
587 tcp_free_sock_data);
588 if (rc != EOK) {
589 async_answer_0(callid, rc);
590 return;
591 }
592
593 async_answer_0(callid, EOK);
594}
595
596static void tcp_sock_getsockopt(tcp_client_t *client, ipc_callid_t callid, ipc_call_t call)
597{
598 log_msg(LVL_DEBUG, "tcp_sock_getsockopt()");
599 async_answer_0(callid, ENOTSUP);
600}
601
602static void tcp_sock_setsockopt(tcp_client_t *client, ipc_callid_t callid, ipc_call_t call)
603{
604 log_msg(LVL_DEBUG, "tcp_sock_setsockopt()");
605 async_answer_0(callid, ENOTSUP);
606}
607
608int tcp_sock_connection(async_sess_t *sess, ipc_callid_t iid, ipc_call_t icall)
609{
610 ipc_callid_t callid;
611 ipc_call_t call;
612 tcp_client_t client;
613
614 /* Accept the connection */
615 async_answer_0(iid, EOK);
616
617 client.sess = sess;
618 socket_cores_initialize(&client.sockets);
619
620 while (true) {
621 callid = async_get_call(&call);
622 if (!IPC_GET_IMETHOD(call))
623 break;
624
625 log_msg(LVL_DEBUG, "tcp_sock_connection: METHOD=%d\n",
626 (int)IPC_GET_IMETHOD(call));
627
628 switch (IPC_GET_IMETHOD(call)) {
629 case NET_SOCKET:
630 tcp_sock_socket(&client, callid, call);
631 break;
632 case NET_SOCKET_BIND:
633 tcp_sock_bind(&client, callid, call);
634 break;
635 case NET_SOCKET_LISTEN:
636 tcp_sock_listen(&client, callid, call);
637 break;
638 case NET_SOCKET_CONNECT:
639 tcp_sock_connect(&client, callid, call);
640 break;
641 case NET_SOCKET_ACCEPT:
642 tcp_sock_accept(&client, callid, call);
643 break;
644 case NET_SOCKET_SEND:
645 tcp_sock_send(&client, callid, call);
646 break;
647 case NET_SOCKET_SENDTO:
648 tcp_sock_sendto(&client, callid, call);
649 break;
650 case NET_SOCKET_RECV:
651 case NET_SOCKET_RECVFROM:
652 tcp_sock_recvfrom(&client, callid, call);
653 break;
654 case NET_SOCKET_CLOSE:
655 tcp_sock_close(&client, callid, call);
656 break;
657 case NET_SOCKET_GETSOCKOPT:
658 tcp_sock_getsockopt(&client, callid, call);
659 break;
660 case NET_SOCKET_SETSOCKOPT:
661 tcp_sock_setsockopt(&client, callid, call);
662 break;
663 default:
664 async_answer_0(callid, ENOTSUP);
665 break;
666 }
667 }
668
669 return EOK;
670}
671
672/**
673 * @}
674 */
Note: See TracBrowser for help on using the repository browser.