source: mainline/uspace/srv/net/tcp/service.c@ 1d4b815

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

Properly wait for connection establishment.

  • Property mode set to 100644
File size: 19.3 KB
Line 
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 <inet/inet.h>
41#include <io/log.h>
42#include <ipc/services.h>
43#include <ipc/tcp.h>
44#include <loc.h>
45#include <macros.h>
46#include <stdlib.h>
47
48#include "conn.h"
49#include "service.h"
50#include "tcp_type.h"
51#include "ucall.h"
52
53#define NAME "tcp"
54
55#define MAX_MSG_SIZE DATA_XFER_LIMIT
56
57static void tcp_ev_data(tcp_cconn_t *);
58static void tcp_ev_connected(tcp_cconn_t *);
59static void tcp_ev_conn_failed(tcp_cconn_t *);
60static void tcp_ev_conn_reset(tcp_cconn_t *);
61
62static void tcp_service_cstate_change(tcp_conn_t *, void *, tcp_cstate_t);
63static void tcp_service_recv_data(tcp_conn_t *, void *);
64
65static tcp_cb_t tcp_service_cb = {
66 .cstate_change = tcp_service_cstate_change,
67 .recv_data = tcp_service_recv_data
68};
69
70static void tcp_service_cstate_change(tcp_conn_t *conn, void *arg,
71 tcp_cstate_t old_state)
72{
73 tcp_cstate_t nstate;
74 tcp_cconn_t *cconn;
75
76 log_msg(LOG_DEFAULT, LVL_DEBUG, "tcp_service_cstate_change()");
77 nstate = conn->cstate;
78 cconn = tcp_uc_get_userptr(conn);
79
80 if ((old_state == st_syn_sent || old_state == st_syn_received) &&
81 (nstate == st_established)) {
82 /* Connection established */
83 tcp_ev_connected(cconn);
84 }
85
86 if (old_state != st_closed && nstate == st_closed && conn->reset) {
87 /* Connection reset */
88 tcp_ev_conn_reset(cconn);
89 }
90
91 /* XXX Failed to establish connection */
92 if (0) tcp_ev_conn_failed(cconn);
93}
94
95static void tcp_service_recv_data(tcp_conn_t *conn, void *arg)
96{
97 tcp_cconn_t *cconn = (tcp_cconn_t *)arg;
98
99 tcp_ev_data(cconn);
100}
101
102static void tcp_ev_data(tcp_cconn_t *cconn)
103{
104 async_exch_t *exch;
105
106 log_msg(LOG_DEFAULT, LVL_DEBUG, "tcp_ev_data()");
107
108 log_msg(LOG_DEFAULT, LVL_DEBUG, "client=%p\n", cconn->client);
109 log_msg(LOG_DEFAULT, LVL_DEBUG, "sess=%p\n", cconn->client->sess);
110
111 exch = async_exchange_begin(cconn->client->sess);
112 aid_t req = async_send_1(exch, TCP_EV_DATA, cconn->id, NULL);
113 async_exchange_end(exch);
114
115 async_forget(req);
116}
117
118static void tcp_ev_connected(tcp_cconn_t *cconn)
119{
120 async_exch_t *exch;
121
122 log_msg(LOG_DEFAULT, LVL_DEBUG, "tcp_ev_connected()");
123
124 exch = async_exchange_begin(cconn->client->sess);
125 aid_t req = async_send_1(exch, TCP_EV_CONNECTED, cconn->id, NULL);
126 async_exchange_end(exch);
127
128 async_forget(req);
129}
130
131static void tcp_ev_conn_failed(tcp_cconn_t *cconn)
132{
133 async_exch_t *exch;
134
135 log_msg(LOG_DEFAULT, LVL_DEBUG, "tcp_ev_conn_failed()");
136
137 exch = async_exchange_begin(cconn->client->sess);
138 aid_t req = async_send_1(exch, TCP_EV_CONN_FAILED, cconn->id, NULL);
139 async_exchange_end(exch);
140
141 async_forget(req);
142}
143
144static void tcp_ev_conn_reset(tcp_cconn_t *cconn)
145{
146 async_exch_t *exch;
147
148 log_msg(LOG_DEFAULT, LVL_DEBUG, "tcp_ev_conn_reset()");
149
150 exch = async_exchange_begin(cconn->client->sess);
151 aid_t req = async_send_1(exch, TCP_EV_CONN_RESET, cconn->id, NULL);
152 async_exchange_end(exch);
153
154 async_forget(req);
155}
156
157static int tcp_cconn_create(tcp_client_t *client, tcp_conn_t *conn,
158 tcp_cconn_t **rcconn)
159{
160 tcp_cconn_t *cconn;
161 sysarg_t id;
162
163 cconn = calloc(1, sizeof(tcp_cconn_t));
164 if (cconn == NULL)
165 return ENOMEM;
166
167 /* Allocate new ID */
168 id = 0;
169 list_foreach (client->cconn, lclient, tcp_cconn_t, cconn) {
170 if (cconn->id >= id)
171 id = cconn->id + 1;
172 }
173
174 cconn->id = id;
175 cconn->client = client;
176 cconn->conn = conn;
177
178 list_append(&cconn->lclient, &client->cconn);
179 *rcconn = cconn;
180 return EOK;
181}
182
183static void tcp_cconn_destroy(tcp_cconn_t *cconn)
184{
185 list_remove(&cconn->lclient);
186 free(cconn);
187}
188
189static int tcp_clistener_create(tcp_client_t *client, tcp_conn_t *conn,
190 tcp_clst_t **rclst)
191{
192 tcp_clst_t *clst;
193 sysarg_t id;
194
195 clst = calloc(1, sizeof(tcp_clst_t));
196 if (clst == NULL)
197 return ENOMEM;
198
199 /* Allocate new ID */
200 id = 0;
201 list_foreach (client->clst, lclient, tcp_clst_t, clst) {
202 if (clst->id >= id)
203 id = clst->id + 1;
204 }
205
206 clst->id = id;
207 clst->client = client;
208 clst->conn = conn;
209
210 list_append(&clst->lclient, &client->clst);
211 *rclst = clst;
212 return EOK;
213}
214
215static void tcp_clistener_destroy(tcp_clst_t *clst)
216{
217 list_remove(&clst->lclient);
218 free(clst);
219}
220
221static int tcp_cconn_get(tcp_client_t *client, sysarg_t id,
222 tcp_cconn_t **rcconn)
223{
224 list_foreach (client->cconn, lclient, tcp_cconn_t, cconn) {
225 if (cconn->id == id) {
226 *rcconn = cconn;
227 return EOK;
228 }
229 }
230
231 return ENOENT;
232}
233
234static int tcp_clistener_get(tcp_client_t *client, sysarg_t id,
235 tcp_clst_t **rclst)
236{
237 list_foreach (client->clst, lclient, tcp_clst_t, clst) {
238 if (clst->id == id) {
239 *rclst = clst;
240 return EOK;
241 }
242 }
243
244 return ENOENT;
245}
246
247
248static int tcp_conn_create_impl(tcp_client_t *client, inet_ep2_t *epp,
249 sysarg_t *rconn_id)
250{
251 tcp_conn_t *conn;
252 tcp_cconn_t *cconn;
253 tcp_sock_t local;
254 tcp_sock_t remote;
255 inet_addr_t local_addr;
256 int rc;
257 tcp_error_t trc;
258 char *slocal;
259 char *sremote;
260
261 log_msg(LOG_DEFAULT, LVL_DEBUG, "tcp_conn_create_impl");
262
263 /* Fill in local address? */
264 if (inet_addr_is_any(&epp->local.addr)) {
265 log_msg(LOG_DEFAULT, LVL_DEBUG, "tcp_conn_create_impl: "
266 "determine local address");
267 rc = inet_get_srcaddr(&epp->remote.addr, 0, &local_addr);
268 if (rc != EOK) {
269 log_msg(LOG_DEFAULT, LVL_DEBUG, "tcp_conn_create_impl: "
270 "cannot determine local address");
271 return rc;
272 }
273 } else {
274 log_msg(LOG_DEFAULT, LVL_DEBUG, "tcp_conn_create_impl: "
275 "local address specified");
276 local_addr = epp->local.addr;
277 }
278
279 /* Allocate local port? */
280 if (epp->local.port == 0) {
281 epp->local.port = 49152; /* XXX */
282 }
283
284 local.addr = local_addr;
285 local.port = epp->local.port;
286 remote.addr = epp->remote.addr;
287 remote.port = epp->remote.port;
288
289 inet_addr_format(&local_addr, &slocal);
290 inet_addr_format(&remote.addr, &sremote);
291 log_msg(LOG_DEFAULT, LVL_DEBUG, "tcp_conn_create: local=%s remote=%s",
292 slocal, sremote);
293
294 trc = tcp_uc_open(&local, &remote, ap_active, tcp_open_nonblock, &conn);
295 if (trc != TCP_EOK)
296 return EIO;
297
298 rc = tcp_cconn_create(client, conn, &cconn);
299 if (rc != EOK) {
300 assert(rc == ENOMEM);
301 tcp_conn_delete(conn);
302 return ENOMEM;
303 }
304
305 /* XXX Is there a race here (i.e. the connection is already active)? */
306 tcp_uc_set_cb(conn, &tcp_service_cb, cconn);
307
308// assoc->cb = &udp_cassoc_cb;
309// assoc->cb_arg = cassoc;
310
311 *rconn_id = cconn->id;
312 return EOK;
313}
314
315static int tcp_conn_destroy_impl(tcp_client_t *client, sysarg_t conn_id)
316{
317 tcp_cconn_t *cconn;
318 int rc;
319
320 rc = tcp_cconn_get(client, conn_id, &cconn);
321 if (rc != EOK) {
322 assert(rc == ENOENT);
323 return ENOENT;
324 }
325
326 tcp_uc_close(cconn->conn);
327 tcp_cconn_destroy(cconn);
328 return EOK;
329}
330
331static int tcp_listener_create_impl(tcp_client_t *client, inet_ep_t *ep,
332 sysarg_t *rlst_id)
333{
334 tcp_conn_t *conn;
335 tcp_clst_t *clst;
336 tcp_sock_t local;
337 int rc;
338 tcp_error_t trc;
339
340 log_msg(LOG_DEFAULT, LVL_DEBUG, "tcp_listener_create_impl");
341
342 local.addr = ep->addr;
343 local.port = ep->port;
344
345 trc = tcp_uc_open(&local, NULL, ap_passive, 0, &conn);
346 if (trc != TCP_EOK)
347 return EIO;
348
349 rc = tcp_clistener_create(client, conn, &clst);
350 if (rc != EOK) {
351 assert(rc == ENOMEM);
352 tcp_conn_delete(conn);
353 return ENOMEM;
354 }
355
356// assoc->cb = &udp_cassoc_cb;
357// assoc->cb_arg = cassoc;
358
359 *rlst_id = clst->id;
360 return EOK;
361}
362
363static int tcp_listener_destroy_impl(tcp_client_t *client, sysarg_t lst_id)
364{
365 tcp_clst_t *clst;
366 int rc;
367
368 rc = tcp_clistener_get(client, lst_id, &clst);
369 if (rc != EOK) {
370 assert(rc == ENOENT);
371 return ENOENT;
372 }
373
374// tcp_uc_close(cconn->conn);
375 tcp_clistener_destroy(clst);
376 return EOK;
377}
378
379static int tcp_conn_send_fin_impl(tcp_client_t *client, sysarg_t conn_id)
380{
381 tcp_cconn_t *cconn;
382 int rc;
383
384 rc = tcp_cconn_get(client, conn_id, &cconn);
385 if (rc != EOK) {
386 assert(rc == ENOENT);
387 return ENOENT;
388 }
389
390 (void) cconn;
391 /* XXX TODO */
392 return EOK;
393}
394
395static int tcp_conn_push_impl(tcp_client_t *client, sysarg_t conn_id)
396{
397 tcp_cconn_t *cconn;
398 int rc;
399
400 rc = tcp_cconn_get(client, conn_id, &cconn);
401 if (rc != EOK) {
402 assert(rc == ENOENT);
403 return ENOENT;
404 }
405
406 (void) cconn;
407 /* XXX TODO */
408 return EOK;
409}
410
411static int tcp_conn_reset_impl(tcp_client_t *client, sysarg_t conn_id)
412{
413 tcp_cconn_t *cconn;
414 int rc;
415
416 rc = tcp_cconn_get(client, conn_id, &cconn);
417 if (rc != EOK) {
418 assert(rc == ENOENT);
419 return ENOENT;
420 }
421
422 tcp_uc_abort(cconn->conn);
423 return EOK;
424}
425
426static int tcp_conn_send_impl(tcp_client_t *client, sysarg_t conn_id,
427 void *data, size_t size)
428{
429 tcp_cconn_t *cconn;
430 int rc;
431
432 rc = tcp_cconn_get(client, conn_id, &cconn);
433 if (rc != EOK)
434 return rc;
435
436 rc = tcp_uc_send(cconn->conn, data, size, 0);
437 if (rc != EOK)
438 return rc;
439
440 return EOK;
441}
442
443static int tcp_conn_recv_impl(tcp_client_t *client, sysarg_t conn_id,
444 void *data, size_t size, size_t *nrecv)
445{
446 tcp_cconn_t *cconn;
447 xflags_t xflags;
448 int rc;
449
450 log_msg(LOG_DEFAULT, LVL_DEBUG, "tcp_conn_recv_impl()");
451
452 rc = tcp_cconn_get(client, conn_id, &cconn);
453 if (rc != EOK) {
454 log_msg(LOG_DEFAULT, LVL_DEBUG, "tcp_conn_recv_impl() - conn not found");
455 return rc;
456 }
457
458 rc = tcp_uc_receive(cconn->conn, data, size, nrecv, &xflags);
459 if (rc != EOK) {
460 switch (rc) {
461 case TCP_EAGAIN:
462 log_msg(LOG_DEFAULT, LVL_DEBUG, "tcp_conn_recv_impl() - EAGAIN");
463 return EAGAIN;
464 default:
465 log_msg(LOG_DEFAULT, LVL_DEBUG, "tcp_conn_recv_impl() - trc=%d", rc);
466 return EIO;
467 }
468 }
469
470 return EOK;
471}
472
473static void tcp_callback_create_srv(tcp_client_t *client, ipc_callid_t iid,
474 ipc_call_t *icall)
475{
476 log_msg(LOG_DEFAULT, LVL_DEBUG, "tcp_callback_create_srv()");
477
478 async_sess_t *sess = async_callback_receive(EXCHANGE_SERIALIZE);
479 if (sess == NULL) {
480 async_answer_0(iid, ENOMEM);
481 return;
482 }
483
484 client->sess = sess;
485 async_answer_0(iid, EOK);
486}
487
488static void tcp_conn_create_srv(tcp_client_t *client, ipc_callid_t iid,
489 ipc_call_t *icall)
490{
491 ipc_callid_t callid;
492 size_t size;
493 inet_ep2_t epp;
494 sysarg_t conn_id;
495 int rc;
496
497 log_msg(LOG_DEFAULT, LVL_DEBUG, "tcp_conn_create_srv()");
498
499 if (!async_data_write_receive(&callid, &size)) {
500 async_answer_0(callid, EREFUSED);
501 async_answer_0(iid, EREFUSED);
502 return;
503 }
504
505 if (size != sizeof(inet_ep2_t)) {
506 async_answer_0(callid, EINVAL);
507 async_answer_0(iid, EINVAL);
508 return;
509 }
510
511 rc = async_data_write_finalize(callid, &epp, size);
512 if (rc != EOK) {
513 async_answer_0(callid, rc);
514 async_answer_0(iid, rc);
515 return;
516 }
517
518 rc = tcp_conn_create_impl(client, &epp, &conn_id);
519 if (rc != EOK) {
520 async_answer_0(iid, rc);
521 return;
522 }
523
524 async_answer_1(iid, EOK, conn_id);
525}
526
527static void tcp_conn_destroy_srv(tcp_client_t *client, ipc_callid_t iid,
528 ipc_call_t *icall)
529{
530 sysarg_t conn_id;
531 int rc;
532
533 log_msg(LOG_DEFAULT, LVL_DEBUG, "tcp_conn_destroy_srv()");
534
535 conn_id = IPC_GET_ARG1(*icall);
536 rc = tcp_conn_destroy_impl(client, conn_id);
537 async_answer_0(iid, rc);
538}
539
540static void tcp_listener_create_srv(tcp_client_t *client, ipc_callid_t iid,
541 ipc_call_t *icall)
542{
543 ipc_callid_t callid;
544 size_t size;
545 inet_ep_t ep;
546 sysarg_t lst_id;
547 int rc;
548
549 log_msg(LOG_DEFAULT, LVL_DEBUG, "tcp_listener_create_srv()");
550
551 if (!async_data_write_receive(&callid, &size)) {
552 async_answer_0(callid, EREFUSED);
553 async_answer_0(iid, EREFUSED);
554 return;
555 }
556
557 if (size != sizeof(inet_ep_t)) {
558 async_answer_0(callid, EINVAL);
559 async_answer_0(iid, EINVAL);
560 return;
561 }
562
563 rc = async_data_write_finalize(callid, &ep, size);
564 if (rc != EOK) {
565 async_answer_0(callid, rc);
566 async_answer_0(iid, rc);
567 return;
568 }
569
570 rc = tcp_listener_create_impl(client, &ep, &lst_id);
571 if (rc != EOK) {
572 async_answer_0(iid, rc);
573 return;
574 }
575
576 async_answer_1(iid, EOK, lst_id);
577}
578
579static void tcp_listener_destroy_srv(tcp_client_t *client, ipc_callid_t iid,
580 ipc_call_t *icall)
581{
582 sysarg_t lst_id;
583 int rc;
584
585 log_msg(LOG_DEFAULT, LVL_DEBUG, "tcp_listener_destroy_srv()");
586
587 lst_id = IPC_GET_ARG1(*icall);
588 rc = tcp_listener_destroy_impl(client, lst_id);
589 async_answer_0(iid, rc);
590}
591
592static void tcp_conn_send_fin_srv(tcp_client_t *client, ipc_callid_t iid,
593 ipc_call_t *icall)
594{
595 sysarg_t conn_id;
596 int rc;
597
598 log_msg(LOG_DEFAULT, LVL_DEBUG, "tcp_conn_send_fin_srv()");
599
600 conn_id = IPC_GET_ARG1(*icall);
601 rc = tcp_conn_send_fin_impl(client, conn_id);
602 async_answer_0(iid, rc);
603}
604
605static void tcp_conn_push_srv(tcp_client_t *client, ipc_callid_t iid,
606 ipc_call_t *icall)
607{
608 sysarg_t conn_id;
609 int rc;
610
611 log_msg(LOG_DEFAULT, LVL_DEBUG, "tcp_conn_push_srv()");
612
613 conn_id = IPC_GET_ARG1(*icall);
614 rc = tcp_conn_push_impl(client, conn_id);
615 async_answer_0(iid, rc);
616}
617
618static void tcp_conn_reset_srv(tcp_client_t *client, ipc_callid_t iid,
619 ipc_call_t *icall)
620{
621 sysarg_t conn_id;
622 int rc;
623
624 log_msg(LOG_DEFAULT, LVL_DEBUG, "tcp_conn_reset_srv()");
625
626 conn_id = IPC_GET_ARG1(*icall);
627 rc = tcp_conn_reset_impl(client, conn_id);
628 async_answer_0(iid, rc);
629}
630
631static void tcp_conn_send_srv(tcp_client_t *client, ipc_callid_t iid,
632 ipc_call_t *icall)
633{
634 ipc_callid_t callid;
635 size_t size;
636 sysarg_t conn_id;
637 void *data;
638 int rc;
639
640 log_msg(LOG_DEFAULT, LVL_DEBUG, "tcp_conn_send_srv())");
641
642 /* Receive message data */
643
644 if (!async_data_write_receive(&callid, &size)) {
645 async_answer_0(callid, EREFUSED);
646 async_answer_0(iid, EREFUSED);
647 return;
648 }
649
650 if (size > MAX_MSG_SIZE) {
651 async_answer_0(callid, EINVAL);
652 async_answer_0(iid, EINVAL);
653 return;
654 }
655
656 data = malloc(size);
657 if (data == NULL) {
658 async_answer_0(callid, ENOMEM);
659 async_answer_0(iid, ENOMEM);
660 }
661
662 rc = async_data_write_finalize(callid, data, size);
663 if (rc != EOK) {
664 async_answer_0(callid, rc);
665 async_answer_0(iid, rc);
666 free(data);
667 return;
668 }
669
670 conn_id = IPC_GET_ARG1(*icall);
671
672 rc = tcp_conn_send_impl(client, conn_id, data, size);
673 if (rc != EOK) {
674 async_answer_0(iid, rc);
675 free(data);
676 return;
677 }
678
679 async_answer_0(iid, EOK);
680 free(data);
681}
682
683static void tcp_conn_recv_srv(tcp_client_t *client, ipc_callid_t iid,
684 ipc_call_t *icall)
685{
686 ipc_callid_t callid;
687 sysarg_t conn_id;
688 size_t size, rsize;
689 void *data;
690 int rc;
691
692 log_msg(LOG_DEFAULT, LVL_DEBUG, "tcp_conn_recv_srv()");
693
694 conn_id = IPC_GET_ARG1(*icall);
695
696 if (!async_data_read_receive(&callid, &size)) {
697 async_answer_0(callid, EREFUSED);
698 async_answer_0(iid, EREFUSED);
699 return;
700 }
701
702 size = max(size, 16384);
703 data = malloc(size);
704 if (data == NULL) {
705 async_answer_0(callid, ENOMEM);
706 async_answer_0(iid, ENOMEM);
707 return;
708 }
709
710 rc = tcp_conn_recv_impl(client, conn_id, data, size, &rsize);
711 if (rc != EOK) {
712 async_answer_0(callid, rc);
713 async_answer_0(iid, rc);
714 free(data);
715 return;
716 }
717
718 rc = async_data_read_finalize(callid, data, size);
719 if (rc != EOK) {
720 async_answer_0(iid, rc);
721 free(data);
722 return;
723 }
724
725 async_answer_1(iid, EOK, rsize);
726 free(data);
727
728 log_msg(LOG_DEFAULT, LVL_DEBUG, "tcp_conn_recv_srv(): OK");
729}
730
731static void tcp_conn_recv_wait_srv(tcp_client_t *client, ipc_callid_t iid,
732 ipc_call_t *icall)
733{
734 ipc_callid_t callid;
735 sysarg_t conn_id;
736 size_t size, rsize;
737 void *data;
738 int rc;
739
740 log_msg(LOG_DEFAULT, LVL_DEBUG, "tcp_conn_recv_wait_srv()");
741
742 conn_id = IPC_GET_ARG1(*icall);
743
744 if (!async_data_read_receive(&callid, &size)) {
745 log_msg(LOG_DEFAULT, LVL_DEBUG, "tcp_conn_recv_wait_srv - data_receive failed");
746 async_answer_0(callid, EREFUSED);
747 async_answer_0(iid, EREFUSED);
748 return;
749 }
750
751 size = min(size, 16384);
752 data = malloc(size);
753 if (data == NULL) {
754 log_msg(LOG_DEFAULT, LVL_DEBUG, "tcp_conn_recv_wait_srv - allocation failed");
755 async_answer_0(callid, ENOMEM);
756 async_answer_0(iid, ENOMEM);
757 return;
758 }
759
760 rc = tcp_conn_recv_impl(client, conn_id, data, size, &rsize);
761 if (rc != EOK) {
762 log_msg(LOG_DEFAULT, LVL_DEBUG, "tcp_conn_recv_wait_srv - recv_impl failed rc=%d", rc);
763 async_answer_0(callid, rc);
764 async_answer_0(iid, rc);
765 free(data);
766 return;
767 }
768
769 rc = async_data_read_finalize(callid, data, size);
770 if (rc != EOK) {
771 log_msg(LOG_DEFAULT, LVL_DEBUG, "tcp_conn_recv_wait_srv - finalize failed");
772 async_answer_0(iid, rc);
773 free(data);
774 return;
775 }
776
777 log_msg(LOG_DEFAULT, LVL_DEBUG, "tcp_conn_recv_wait_srv(): rsize=%zu", size);
778 async_answer_1(iid, EOK, rsize);
779 free(data);
780
781 log_msg(LOG_DEFAULT, LVL_DEBUG, "tcp_conn_recv_wait_srv(): OK");
782}
783
784#include <mem.h>
785static void tcp_client_conn(ipc_callid_t iid, ipc_call_t *icall, void *arg)
786{
787 tcp_client_t client;
788
789 /* Accept the connection */
790 async_answer_0(iid, EOK);
791
792 log_msg(LOG_DEFAULT, LVL_DEBUG, "tcp_client_conn() - client=%p",
793 &client);
794
795 memset(&client, 0, sizeof(client));
796 client.sess = NULL;
797 list_initialize(&client.cconn);
798 list_initialize(&client.clst);
799// list_initialize(&client.crcv_queue);
800
801 while (true) {
802 log_msg(LOG_DEFAULT, LVL_DEBUG, "tcp_client_conn: wait req");
803 ipc_call_t call;
804 ipc_callid_t callid = async_get_call(&call);
805 sysarg_t method = IPC_GET_IMETHOD(call);
806
807 log_msg(LOG_DEFAULT, LVL_DEBUG, "tcp_client_conn: method=%d",
808 (int)method);
809 if (!method) {
810 /* The other side has hung up */
811 async_answer_0(callid, EOK);
812 return;
813 }
814
815 switch (method) {
816 case TCP_CALLBACK_CREATE:
817 tcp_callback_create_srv(&client, callid, &call);
818 break;
819 case TCP_CONN_CREATE:
820 tcp_conn_create_srv(&client, callid, &call);
821 break;
822 case TCP_CONN_DESTROY:
823 tcp_conn_destroy_srv(&client, callid, &call);
824 break;
825 case TCP_LISTENER_CREATE:
826 tcp_listener_create_srv(&client, callid, &call);
827 break;
828 case TCP_LISTENER_DESTROY:
829 tcp_listener_destroy_srv(&client, callid, &call);
830 break;
831 case TCP_CONN_SEND_FIN:
832 tcp_conn_send_fin_srv(&client, callid, &call);
833 break;
834 case TCP_CONN_PUSH:
835 tcp_conn_push_srv(&client, callid, &call);
836 break;
837 case TCP_CONN_RESET:
838 tcp_conn_reset_srv(&client, callid, &call);
839 break;
840 case TCP_CONN_SEND:
841 tcp_conn_send_srv(&client, callid, &call);
842 break;
843 case TCP_CONN_RECV:
844 tcp_conn_recv_srv(&client, callid, &call);
845 break;
846 case TCP_CONN_RECV_WAIT:
847 tcp_conn_recv_wait_srv(&client, callid, &call);
848 break;
849 default:
850 async_answer_0(callid, ENOTSUP);
851 break;
852 }
853 }
854 log_msg(LOG_DEFAULT, LVL_DEBUG,
855 "tcp_client_conn TERMINATED ***************************");
856}
857
858int tcp_service_init(void)
859{
860 int rc;
861 service_id_t sid;
862
863 async_set_client_connection(tcp_client_conn);
864
865 rc = loc_server_register(NAME);
866 if (rc != EOK) {
867 log_msg(LOG_DEFAULT, LVL_ERROR, "Failed registering server.");
868 return EIO;
869 }
870
871 rc = loc_service_register(SERVICE_NAME_TCP, &sid);
872 if (rc != EOK) {
873 log_msg(LOG_DEFAULT, LVL_ERROR, "Failed registering service.");
874 return EIO;
875 }
876
877 return EOK;
878}
879
880/**
881 * @}
882 */
Note: See TracBrowser for help on using the repository browser.