source: mainline/uspace/srv/net/tl/tcp/sock.c@ 0ac2158

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

Determine local IP address, fill it in pseudo header.

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