vm: restore stacktrace on SIGSEGV
[minix.git] / servers / lwip / tcp.c
blob077b964df0318cd5d77defc38f59e9765967a55d
1 #include <stdlib.h>
2 #include <assert.h>
3 #include <minix/sysutil.h>
5 #include <sys/ioc_net.h>
6 #include <net/gen/in.h>
7 #include <net/gen/tcp.h>
8 #include <net/gen/tcp_io.h>
10 #include <lwip/tcp.h>
11 #include <lwip/tcp_impl.h>
12 #include <lwip/ip_addr.h>
14 #include <minix/netsock.h>
15 #include "proto.h"
17 #define TCP_BUF_SIZE (32 << 10)
19 #define sock_alloc_buf(s) debug_malloc(s)
20 #define sock_free_buf(x) debug_free(x)
22 static int do_tcp_debug;
24 #if 0
25 #define debug_tcp_print(str, ...) printf("LWIP %s:%d : " str "\n", \
26 __func__, __LINE__, ##__VA_ARGS__)
27 #else
28 #define debug_tcp_print(...) debug_print(__VA_ARGS__)
29 #endif
31 struct wbuf {
32 unsigned len;
33 unsigned written;
34 unsigned unacked;
35 unsigned rem_len;
36 struct wbuf * next;
37 char data[];
40 struct wbuf_chain {
41 struct wbuf * head;
42 struct wbuf * tail;
43 struct wbuf * unsent; /* points to the first buffer that contains unsent
44 data. It may point anywhere between head and
45 tail */
48 static void tcp_error_callback(void *arg, err_t err)
50 int perr;
51 struct socket * sock = (struct socket *) arg;
53 debug_tcp_print("socket num %ld err %d", get_sock_num(sock), err);
55 switch (err) {
56 case ERR_RST:
57 perr = ECONNREFUSED;
58 break;
59 case ERR_CLSD:
60 perr = EPIPE;
61 break;
62 case ERR_CONN:
63 perr = ENOTCONN;
64 break;
65 default:
66 perr = EIO;
69 if (sock->flags & SOCK_FLG_OP_PENDING) {
70 sock_reply(sock, perr);
71 sock->flags &= ~SOCK_FLG_OP_PENDING;
72 } else if (sock_select_set(sock))
73 sock_select_notify(sock);
75 * When error callback is called the tcb either does not exist anymore
76 * or is going to be deallocated soon after. We must not use the pcb
77 * anymore
79 sock->pcb = NULL;
82 static int tcp_fill_new_socket(struct socket * sock, struct tcp_pcb * pcb)
84 struct wbuf_chain * wc;
86 if (!(wc = malloc(sizeof(struct wbuf_chain))))
87 return ENOMEM;
89 wc-> head = wc->tail = wc->unsent = NULL;
90 sock->buf = wc;
91 sock->buf_size = 0;
93 sock->pcb = pcb;
94 tcp_arg(pcb, sock);
95 tcp_err(pcb, tcp_error_callback);
96 tcp_nagle_disable(pcb);
98 return OK;
101 static int tcp_op_open(struct socket * sock, __unused message * m)
103 struct tcp_pcb * pcb;
104 int ret;
106 debug_tcp_print("socket num %ld", get_sock_num(sock));
108 if (!(pcb = tcp_new()))
109 return ENOMEM;
110 debug_tcp_print("new tcp pcb %p\n", pcb);
112 if ((ret = tcp_fill_new_socket(sock, pcb) != OK))
113 tcp_abandon(pcb, 0);
115 return ret;
118 static void tcp_recv_free(__unused void * data)
120 pbuf_free((struct pbuf *) data);
123 static void tcp_backlog_free(void * data)
125 tcp_abort((struct tcp_pcb *) data);
128 static void free_wbuf_chain(struct wbuf_chain * wc)
130 struct wbuf * wb;
132 assert(wc != NULL);
134 wb = wc->head;
135 while (wb) {
136 struct wbuf * w = wb;
137 debug_tcp_print("freeing wbuf %p", wb);
138 wb = wb->next;
139 debug_free(w);
142 debug_free(wc);
145 static void tcp_op_close(struct socket * sock, __unused message * m)
147 debug_tcp_print("socket num %ld", get_sock_num(sock));
149 if (sock->flags & SOCK_FLG_OP_LISTENING)
150 sock_dequeue_data_all(sock, tcp_backlog_free);
151 else
152 sock_dequeue_data_all(sock, tcp_recv_free);
153 debug_tcp_print("dequed RX data");
155 if (sock->pcb) {
156 int err;
158 /* we are not able to handle any callback anymore */
159 tcp_arg((struct tcp_pcb *)sock->pcb, NULL);
160 tcp_err((struct tcp_pcb *)sock->pcb, NULL);
161 tcp_sent((struct tcp_pcb *)sock->pcb, NULL);
162 tcp_recv((struct tcp_pcb *)sock->pcb, NULL);
164 err = tcp_close(sock->pcb);
165 assert(err == ERR_OK);
166 sock->pcb = NULL;
168 debug_tcp_print("freed pcb");
170 if (sock->buf) {
171 free_wbuf_chain((struct wbuf_chain *) sock->buf);
172 sock->buf = NULL;
174 debug_tcp_print("freed TX data");
176 sock_reply_close(sock, OK);
177 debug_tcp_print("socket unused");
179 /* mark it as unused */
180 sock->ops = NULL;
183 __unused static void print_tcp_payload(unsigned char * buf, int len)
185 int i;
187 printf("LWIP tcp payload (%d) :\n", len);
188 for (i = 0; i < len; i++, buf++) {
189 printf("%02x ", buf[0]);
190 if (i % 8 == 7)
191 kputc('\n');
193 kputc('\n');
196 static int read_from_tcp(struct socket * sock, message * m)
198 unsigned rem_buf, written = 0;
199 struct pbuf * p;
201 assert(!(sock->flags & SOCK_FLG_OP_LISTENING) && sock->recv_head);
203 rem_buf = m->COUNT;
205 debug_tcp_print("socket num %ld recv buff sz %d", get_sock_num(sock), rem_buf);
207 p = (struct pbuf *)sock->recv_head->data;
208 while (rem_buf) {
209 int err;
211 if (rem_buf >= p->len) {
212 struct pbuf * np;
215 * FIXME perhaps copy this to a local buffer and do a
216 * single copy to user then
218 #if 0
219 print_tcp_payload(p->payload, p->len);
220 #endif
221 err = copy_to_user(m->m_source, p->payload, p->len,
222 (cp_grant_id_t) m->IO_GRANT, written);
223 if (err != OK)
224 goto cp_error;
225 sock->recv_data_size -= p->len;
227 debug_tcp_print("whole pbuf copied (%d bytes)", p->len);
228 rem_buf -= p->len;
229 written += p->len;
231 if ((np = p->next)) {
232 pbuf_ref(np);
233 if (pbuf_free(p) != 1)
234 panic("LWIP : pbuf_free != 1");
236 * Mark where we are going to continue if an
237 * error occurs
239 sock->recv_head->data = np;
240 p = np;
241 } else {
242 sock_dequeue_data(sock);
243 pbuf_free(p);
244 if (sock->recv_head)
245 p = (struct pbuf *)sock->recv_head->data;
246 else
247 break;
250 if (rem_buf == 0)
251 break;
252 } else {
254 * It must be PBUF_RAM for us to be able to shift the
255 * payload pointer
257 assert(p->type == PBUF_RAM);
259 #if 0
260 print_tcp_payload(p->payload, rem_buf);
261 #endif
262 err = copy_to_user(m->m_source, p->payload, rem_buf,
263 (cp_grant_id_t) m->IO_GRANT, written);
264 if (err != OK)
265 goto cp_error;
266 sock->recv_data_size -= rem_buf;
268 debug_tcp_print("partial pbuf copied (%d bytes)", rem_buf);
270 * The whole pbuf hasn't been copied out, we only shift
271 * the payload pointer to remember where to continue
272 * next time
274 pbuf_header(p, -rem_buf);
275 written += rem_buf;
276 break;
280 debug_tcp_print("%d bytes written to userspace", written);
281 //printf("%d wr, queue %d\n", written, sock->recv_data_size);
282 tcp_recved((struct tcp_pcb *) sock->pcb, written);
283 return written;
285 cp_error:
286 if (written) {
287 debug_tcp_print("%d bytes written to userspace", written);
288 return written;
289 } else
290 return EFAULT;
293 static void tcp_op_read(struct socket * sock, message * m, int blk)
295 debug_tcp_print("socket num %ld", get_sock_num(sock));
297 if (!sock->pcb || ((struct tcp_pcb *) sock->pcb)->state !=
298 ESTABLISHED) {
299 debug_tcp_print("Connection not established\n");
300 sock_reply(sock, ENOTCONN);
301 return;
303 if (sock->recv_head) {
304 /* data available receive immeditely */
305 int ret = read_from_tcp(sock, m);
306 debug_tcp_print("read op finished");
307 sock_reply(sock, ret);
308 } else {
309 if (sock->flags & SOCK_FLG_CLOSED) {
310 printf("socket %ld already closed!!! call from %d\n",
311 get_sock_num(sock), m->USER_ENDPT);
312 do_tcp_debug = 1;
313 sock_reply(sock, 0);
314 return;
316 if (!blk) {
317 debug_tcp_print("reading would block -> EAGAIN");
318 sock_reply(sock, EAGAIN);
319 return;
321 /* operation is being processed */
322 debug_tcp_print("no data to read, suspending");
323 sock->flags |= SOCK_FLG_OP_PENDING | SOCK_FLG_OP_READING;
327 static struct wbuf * wbuf_add(struct socket * sock, unsigned sz)
329 struct wbuf * wbuf;
330 struct wbuf_chain * wc = (struct wbuf_chain *)sock->buf;
332 assert(wc);
334 wbuf = debug_malloc(sizeof(struct wbuf) + sz);
335 if (!wbuf)
336 return NULL;
338 wbuf->len = sz;
339 wbuf->written = wbuf->unacked = 0;
340 wbuf->next = NULL;
342 if (wc->head == NULL)
343 wc->head = wc->tail = wbuf;
344 else {
345 wc->tail->next = wbuf;
346 wc->tail = wbuf;
349 sock->buf_size += sz;
350 debug_tcp_print("buffer %p size %d\n", wbuf, sock->buf_size);
352 return wbuf;
355 static struct wbuf * wbuf_ack_sent(struct socket * sock, unsigned sz)
357 struct wbuf_chain * wc = (struct wbuf_chain *) sock->buf;
358 struct wbuf ** wb;
360 wb = &wc->head;
361 while (sz && *wb) {
362 if ((*wb)->unacked <= sz) {
363 struct wbuf * w;
364 assert((*wb)->rem_len == 0);
365 w = *wb;
366 *wb = w->next;
367 sock->buf_size -= w->len;
368 sz -= w->unacked;
369 debug_tcp_print("whole buffer acked (%d / %d), removed",
370 w->unacked, w->len);
371 debug_free(w);
372 } else {
373 (*wb)->unacked -= sz;
374 (*wb)->written += sz;
375 debug_tcp_print("acked %d / %d bytes", sz, (*wb)->len);
376 sz = 0;
380 /* did we write out more than we had? */
381 assert(sz == 0);
383 if (wc->head == NULL)
384 wc->tail = NULL;
385 debug_tcp_print("buffer size %d\n", sock->buf_size);
387 return wc->head;
390 static void tcp_op_write(struct socket * sock, message * m, __unused int blk)
392 int ret;
393 struct wbuf * wbuf;
394 unsigned snd_buf_len, usr_buf_len;
395 u8_t flgs = 0;
398 if (!sock->pcb) {
399 sock_reply(sock, ENOTCONN);
400 return;
403 usr_buf_len = m->COUNT;
404 debug_tcp_print("socket num %ld data size %d",
405 get_sock_num(sock), usr_buf_len);
408 * Let at most one buffer grow beyond TCP_BUF_SIZE. This is to minimize
409 * small writes from userspace if only a few bytes were sent before
411 if (sock->buf_size >= TCP_BUF_SIZE) {
412 /* FIXME do not block for now */
413 debug_tcp_print("WARNING : tcp buffers too large, cannot allocate more");
414 sock_reply(sock, ENOMEM);
415 return;
418 * Never let the allocated buffers grow more than to 2xTCP_BUF_SIZE and
419 * never copy more than space available
421 usr_buf_len = (usr_buf_len > TCP_BUF_SIZE ? TCP_BUF_SIZE : usr_buf_len);
422 wbuf = wbuf_add(sock, usr_buf_len);
423 debug_tcp_print("new wbuf for %d bytes", wbuf->len);
425 if (!wbuf) {
426 debug_tcp_print("cannot allocate new buffer of %d bytes", usr_buf_len);
427 sock_reply(sock, ENOMEM);
430 if ((ret = copy_from_user(m->m_source, wbuf->data, usr_buf_len,
431 (cp_grant_id_t) m->IO_GRANT, 0)) != OK) {
432 sock_reply(sock, ret);
433 return;
436 wbuf->written = 0;
437 wbuf->rem_len = usr_buf_len;
440 * If a writing operation is already in progress, we just enqueue the
441 * data and quit.
443 if (sock->flags & SOCK_FLG_OP_WRITING) {
444 struct wbuf_chain * wc = (struct wbuf_chain *)sock->buf;
446 * We are adding a buffer with unsent data. If we don't have any other
447 * unsent data, set the pointer to this buffer.
449 if (wc->unsent == NULL) {
450 wc->unsent = wbuf;
451 debug_tcp_print("unsent %p remains %d\n", wbuf, wbuf->rem_len);
453 debug_tcp_print("returns %d\n", usr_buf_len);
454 sock_reply(sock, usr_buf_len);
456 * We cannot accept new operations (write). We set the flag
457 * after sending reply not to revive only. We could deadlock.
459 if (sock->buf_size >= TCP_BUF_SIZE)
460 sock->flags |= SOCK_FLG_OP_PENDING;
462 return;
466 * Start sending data if the operation is not in progress yet. The
467 * current buffer is the nly one we have, we cannot send more.
470 snd_buf_len = tcp_sndbuf((struct tcp_pcb *)sock->pcb);
471 debug_tcp_print("tcp can accept %d bytes", snd_buf_len);
473 wbuf->unacked = (snd_buf_len < wbuf->rem_len ? snd_buf_len : wbuf->rem_len);
474 wbuf->rem_len -= wbuf->unacked;
476 if (wbuf->rem_len) {
477 flgs = TCP_WRITE_FLAG_MORE;
479 * Remember that this buffer has some data which we didn't pass
480 * to tcp yet.
482 ((struct wbuf_chain *)sock->buf)->unsent = wbuf;
483 debug_tcp_print("unsent %p remains %d\n", wbuf, wbuf->rem_len);
486 ret = tcp_write((struct tcp_pcb *)sock->pcb, wbuf->data,
487 wbuf->unacked, flgs);
488 tcp_output((struct tcp_pcb *)sock->pcb);
489 debug_tcp_print("%d bytes to tcp", wbuf->unacked);
491 if (ret == ERR_OK) {
493 * Operation is being processed, no need to remember the message
494 * in this case, we are going to reply immediatly
496 debug_tcp_print("returns %d\n", usr_buf_len);
497 sock_reply(sock, usr_buf_len);
498 sock->flags |= SOCK_FLG_OP_WRITING;
499 if (sock->buf_size >= TCP_BUF_SIZE)
500 sock->flags |= SOCK_FLG_OP_PENDING;
501 } else
502 sock_reply(sock, EIO);
505 static void tcp_set_conf(struct socket * sock, message * m)
507 int err;
508 nwio_tcpconf_t tconf;
509 struct tcp_pcb * pcb = (struct tcp_pcb *) sock->pcb;
511 debug_tcp_print("socket num %ld", get_sock_num(sock));
513 assert(pcb);
515 err = copy_from_user(m->m_source, &tconf, sizeof(tconf),
516 (cp_grant_id_t) m->IO_GRANT, 0);
518 if (err != OK)
519 sock_reply(sock, err);
521 debug_tcp_print("tconf.nwtc_flags = 0x%lx", tconf.nwtc_flags);
522 debug_tcp_print("tconf.nwtc_remaddr = 0x%x",
523 (unsigned int) tconf.nwtc_remaddr);
524 debug_tcp_print("tconf.nwtc_remport = 0x%x", ntohs(tconf.nwtc_remport));
525 debug_tcp_print("tconf.nwtc_locaddr = 0x%x",
526 (unsigned int) tconf.nwtc_locaddr);
527 debug_tcp_print("tconf.nwtc_locport = 0x%x", ntohs(tconf.nwtc_locport));
529 sock->usr_flags = tconf.nwtc_flags;
531 if (sock->usr_flags & NWTC_SET_RA)
532 pcb->remote_ip.addr = tconf.nwtc_remaddr;
533 if (sock->usr_flags & NWTC_SET_RP)
534 pcb->remote_port = ntohs(tconf.nwtc_remport);
536 if (sock->usr_flags & NWTC_LP_SET) {
537 /* FIXME the user library can only bind to ANY anyway */
538 if (tcp_bind(pcb, IP_ADDR_ANY, ntohs(tconf.nwtc_locport)) == ERR_USE) {
539 sock_reply(sock, EADDRINUSE);
540 return;
544 sock_reply(sock, OK);
547 static void tcp_get_conf(struct socket * sock, message * m)
549 int err;
550 nwio_tcpconf_t tconf;
551 struct tcp_pcb * pcb = (struct tcp_pcb *) sock->pcb;
553 debug_tcp_print("socket num %ld", get_sock_num(sock));
555 assert(pcb);
557 tconf.nwtc_locaddr = pcb->local_ip.addr;
558 tconf.nwtc_locport = htons(pcb->local_port);
559 tconf.nwtc_remaddr = pcb->remote_ip.addr;
560 tconf.nwtc_remport = htons(pcb->remote_port);
561 tconf.nwtc_flags = sock->usr_flags;
563 debug_tcp_print("tconf.nwtc_flags = 0x%lx", tconf.nwtc_flags);
564 debug_tcp_print("tconf.nwtc_remaddr = 0x%x",
565 (unsigned int) tconf.nwtc_remaddr);
566 debug_tcp_print("tconf.nwtc_remport = 0x%x", ntohs(tconf.nwtc_remport));
567 debug_tcp_print("tconf.nwtc_locaddr = 0x%x",
568 (unsigned int) tconf.nwtc_locaddr);
569 debug_tcp_print("tconf.nwtc_locport = 0x%x", ntohs(tconf.nwtc_locport));
571 if ((unsigned) m->COUNT < sizeof(tconf)) {
572 sock_reply(sock, EINVAL);
573 return;
576 err = copy_to_user(m->m_source, &tconf, sizeof(tconf),
577 (cp_grant_id_t) m->IO_GRANT, 0);
579 if (err != OK)
580 sock_reply(sock, err);
582 sock_reply(sock, OK);
585 static int enqueue_rcv_data(struct socket * sock, struct pbuf * pbuf)
587 /* Do not enqueue more data than allowed */
588 if (0 && sock->recv_data_size > 4 * TCP_BUF_SIZE)
589 return ERR_MEM;
591 if (sock_enqueue_data(sock, pbuf, pbuf->tot_len) != OK) {
592 debug_tcp_print("data enqueueing failed");
593 return ERR_MEM;
595 debug_tcp_print("enqueued %d bytes", pbuf->tot_len);
596 //printf("enqueued %d bytes, queue %d\n", pbuf->tot_len, sock->recv_data_size);
598 return ERR_OK;
601 static err_t tcp_recv_callback(void *arg,
602 struct tcp_pcb *tpcb,
603 struct pbuf *pbuf,
604 err_t err)
606 int ret, enqueued = 0;
607 struct socket * sock = (struct socket *) arg;
609 debug_tcp_print("socket num %ld", get_sock_num(sock));
611 if (sock->pcb == NULL) {
612 if (sock_select_set(sock))
613 sock_select_notify(sock);
614 return ERR_OK;
617 assert((struct tcp_pcb *) sock->pcb == tpcb);
619 if (err != ERR_OK)
620 return ERR_OK;
621 if (!pbuf) {
622 debug_tcp_print("tcp stream closed on the remote side");
623 // sock->flags |= SOCK_FLG_CLOSED;
625 /* wake up the reader and report EOF */
626 if (sock->flags & SOCK_FLG_OP_PENDING &&
627 sock->flags & SOCK_FLG_OP_READING) {
628 sock_reply(sock, 0);
629 sock->flags &= ~(SOCK_FLG_OP_PENDING |
630 SOCK_FLG_OP_READING);
632 #if 0
633 /* if there are any undelivered data, drop them */
634 sock_dequeue_data_all(sock, tcp_recv_free);
635 tcp_abandon(tpcb, 0);
636 sock->pcb = NULL;
637 #endif
639 return ERR_OK;
643 * FIXME we always enqueue the data first. If the head is empty and read
644 * operation is pending we could try to deliver immeditaly without
645 * enqueueing
647 if (enqueue_rcv_data(sock, pbuf) == ERR_OK)
648 enqueued = 1;
651 * Deliver data if there is a pending read operation, otherwise notify
652 * select if the socket is being monitored
654 if (sock->flags & SOCK_FLG_OP_PENDING) {
655 if (sock->flags & SOCK_FLG_OP_READING) {
656 ret = read_from_tcp(sock, &sock->mess);
657 debug_tcp_print("read op finished");
658 sock_reply(sock, ret);
659 sock->flags &= ~(SOCK_FLG_OP_PENDING |
660 SOCK_FLG_OP_READING);
662 } else if (!(sock->flags & SOCK_FLG_OP_WRITING) &&
663 sock_select_rw_set(sock))
664 sock_select_notify(sock);
666 /* perhaps we have deliverd some data to user, try to enqueue again */
667 if (!enqueued) {
668 return enqueue_rcv_data(sock, pbuf);
669 } else
670 return ERR_OK;
673 static err_t tcp_sent_callback(void *arg, struct tcp_pcb *tpcb, u16_t len)
675 struct socket * sock = (struct socket *) arg;
676 struct wbuf * wbuf;
677 struct wbuf_chain * wc = (struct wbuf_chain *) sock->buf;
678 unsigned snd_buf_len;
679 int ret;
681 debug_tcp_print("socket num %ld", get_sock_num(sock));
683 /* an error might have had happen */
684 if (sock->pcb == NULL) {
685 if (sock_select_set(sock))
686 sock_select_notify(sock);
687 return ERR_OK;
690 assert((struct tcp_pcb *)sock->pcb == tpcb);
692 /* operation must have been canceled, do not send any other data */
693 if (!sock->flags & SOCK_FLG_OP_PENDING)
694 return ERR_OK;
696 wbuf = wbuf_ack_sent(sock, len);
698 if (wbuf == NULL) {
699 debug_tcp_print("all data acked, nothing more to send");
700 sock->flags &= ~SOCK_FLG_OP_WRITING;
701 if (!(sock->flags & SOCK_FLG_OP_READING))
702 sock->flags &= ~SOCK_FLG_OP_PENDING;
703 /* no reviving, we must notify. Write and read possible */
704 if (sock_select_rw_set(sock))
705 sock_select_notify(sock);
706 return ERR_OK;
709 /* we have just freed some space, write will be accepted */
710 if (sock->buf_size < TCP_BUF_SIZE && sock_select_rw_set(sock)) {
711 if (!(sock->flags & SOCK_FLG_OP_READING)) {
712 sock->flags &= ~SOCK_FLG_OP_PENDING;
713 sock_select_notify(sock);
718 * Check if there is some space for new data, there should be, we just
719 * got a confirmation that some data reached the other end of the
720 * connection
722 snd_buf_len = tcp_sndbuf(tpcb);
723 assert(snd_buf_len > 0);
724 debug_tcp_print("tcp can accept %d bytes", snd_buf_len);
726 if (!wc->unsent) {
727 debug_tcp_print("nothing to send");
728 return ERR_OK;
731 wbuf = wc->unsent;
732 while (wbuf) {
733 unsigned towrite;
734 u8_t flgs = 0;
736 towrite = (snd_buf_len < wbuf->rem_len ?
737 snd_buf_len : wbuf->rem_len);
738 wbuf->rem_len -= towrite;
739 debug_tcp_print("data to send, sending %d", towrite);
741 if (wbuf->rem_len || wbuf->next)
742 flgs = TCP_WRITE_FLAG_MORE;
743 ret = tcp_write(tpcb, wbuf->data + wbuf->written + wbuf->unacked,
744 towrite, flgs);
745 debug_tcp_print("%d bytes to tcp", towrite);
747 /* tcp_output() is called once we return from this callback */
749 if (ret != ERR_OK) {
750 debug_print("tcp_write() failed (%d), written %d"
751 , ret, wbuf->written);
752 sock->flags &= ~(SOCK_FLG_OP_PENDING | SOCK_FLG_OP_WRITING);
753 /* no reviving, we must notify. Write and read possible */
754 if (sock_select_rw_set(sock))
755 sock_select_notify(sock);
756 return ERR_OK;
759 wbuf->unacked += towrite;
760 snd_buf_len -= towrite;
761 debug_tcp_print("tcp still accepts %d bytes\n", snd_buf_len);
763 if (snd_buf_len) {
764 assert(wbuf->rem_len == 0);
765 wbuf = wbuf->next;
766 wc->unsent = wbuf;
767 if (wbuf)
768 debug_tcp_print("unsent %p remains %d\n",
769 wbuf, wbuf->rem_len);
770 else {
771 debug_tcp_print("nothing to send");
773 } else
774 break;
777 return ERR_OK;
780 static err_t tcp_connected_callback(void *arg,
781 struct tcp_pcb *tpcb,
782 __unused err_t err)
784 struct socket * sock = (struct socket *) arg;
786 debug_tcp_print("socket num %ld err %d", get_sock_num(sock), err);
788 if (sock->pcb == NULL) {
789 if (sock_select_set(sock))
790 sock_select_notify(sock);
791 return ERR_OK;
794 assert((struct tcp_pcb *)sock->pcb == tpcb);
796 tcp_sent(tpcb, tcp_sent_callback);
797 tcp_recv(tpcb, tcp_recv_callback);
798 sock_reply(sock, OK);
799 sock->flags &= ~(SOCK_FLG_OP_PENDING | SOCK_FLG_OP_CONNECTING);
801 /* revive does the sock_select_notify() for us */
803 return ERR_OK;
806 static void tcp_op_connect(struct socket * sock)
808 ip_addr_t remaddr;
809 struct tcp_pcb * pcb;
810 err_t err;
812 debug_tcp_print("socket num %ld", get_sock_num(sock));
814 * Connecting is going to send some packets. Unless an immediate error
815 * occurs this operation is going to block
817 sock->flags |= SOCK_FLG_OP_PENDING | SOCK_FLG_OP_CONNECTING;
819 /* try to connect now */
820 pcb = (struct tcp_pcb *) sock->pcb;
821 remaddr = pcb->remote_ip;
822 err = tcp_connect(pcb, &remaddr, pcb->remote_port,
823 tcp_connected_callback);
824 if (err == ERR_VAL)
825 panic("Wrong tcp_connect arguments");
826 if (err != ERR_OK)
827 panic("Other tcp_connect error %d\n", err);
830 static int tcp_do_accept(struct socket * listen_sock,
831 message * m,
832 struct tcp_pcb * newpcb)
834 struct socket * newsock;
835 unsigned sock_num;
836 int ret;
838 debug_tcp_print("socket num %ld", get_sock_num(listen_sock));
840 if ((ret = copy_from_user(m->m_source, &sock_num, sizeof(sock_num),
841 (cp_grant_id_t) m->IO_GRANT, 0)) != OK)
842 return EFAULT;
843 if (!is_valid_sock_num(sock_num))
844 return EBADF;
846 newsock = get_sock(sock_num);
847 assert(newsock->pcb); /* because of previous open() */
849 /* we really want to forget about this socket */
850 tcp_err((struct tcp_pcb *)newsock->pcb, NULL);
851 tcp_abandon((struct tcp_pcb *)newsock->pcb, 0);
853 tcp_arg(newpcb, newsock);
854 tcp_err(newpcb, tcp_error_callback);
855 tcp_sent(newpcb, tcp_sent_callback);
856 tcp_recv(newpcb, tcp_recv_callback);
857 tcp_nagle_disable(newpcb);
858 tcp_accepted(((struct tcp_pcb *)(listen_sock->pcb)));
859 newsock->pcb = newpcb;
861 debug_tcp_print("Accepted new connection using socket %d\n", sock_num);
863 return OK;
866 static err_t tcp_accept_callback(void *arg, struct tcp_pcb *newpcb, err_t err)
868 struct socket * sock = (struct socket *) arg;
870 debug_tcp_print("socket num %ld", get_sock_num(sock));
872 assert(err == ERR_OK && newpcb);
873 assert(sock->flags & SOCK_FLG_OP_LISTENING);
875 if (sock->flags & SOCK_FLG_OP_PENDING) {
876 int ret;
878 ret = tcp_do_accept(sock, &sock->mess, newpcb);
879 sock_reply(sock, ret);
880 sock->flags &= ~SOCK_FLG_OP_PENDING;
881 if (ret == OK) {
882 return ERR_OK;
884 /* in case of an error fall through */
887 /* If we cannot accept rightaway we enqueue the connection for later */
889 debug_tcp_print("Enqueue connection sock %ld pcb %p\n",
890 get_sock_num(sock), newpcb);
891 if (sock_enqueue_data(sock, newpcb, 1) != OK) {
892 tcp_abort(newpcb);
893 return ERR_ABRT;
895 if (sock_select_read_set(sock))
896 sock_select_notify(sock);
898 return ERR_OK;
901 static void tcp_op_listen(struct socket * sock, message * m)
903 int backlog, err;
904 struct tcp_pcb * new_pcb;
906 debug_tcp_print("socket num %ld", get_sock_num(sock));
908 err = copy_from_user(m->m_source, &backlog, sizeof(backlog),
909 (cp_grant_id_t) m->IO_GRANT, 0);
911 new_pcb = tcp_listen_with_backlog((struct tcp_pcb *) sock->pcb,
912 (u8_t) backlog);
913 debug_tcp_print("listening pcb %p", new_pcb);
915 if (!new_pcb) {
916 debug_tcp_print("Cannot listen on socket %ld", get_sock_num(sock));
917 sock_reply(sock, EGENERIC);
918 return;
921 /* advertise that this socket is willing to accept connections */
922 tcp_accept(new_pcb, tcp_accept_callback);
923 sock->flags |= SOCK_FLG_OP_LISTENING;
925 sock->pcb = new_pcb;
926 sock_reply(sock, OK);
929 static void tcp_op_accept(struct socket * sock, message * m)
931 debug_tcp_print("socket num %ld", get_sock_num(sock));
933 if (!(sock->flags & SOCK_FLG_OP_LISTENING)) {
934 debug_tcp_print("socket %ld does not listen\n", get_sock_num(sock));
935 sock_reply(sock, EINVAL);
936 return;
939 /* there is a connection ready to be accepted */
940 if (sock->recv_head) {
941 int ret;
942 struct tcp_pcb * pcb;
944 pcb = (struct tcp_pcb *) sock->recv_head->data;
945 assert(pcb);
947 ret = tcp_do_accept(sock, m, pcb);
948 sock_reply(sock, ret);
949 if (ret == OK)
950 sock_dequeue_data(sock);
951 return;
954 debug_tcp_print("no ready connection, suspending\n");
956 sock->flags |= SOCK_FLG_OP_PENDING;
959 static void tcp_op_shutdown_tx(struct socket * sock)
961 err_t err;
963 debug_tcp_print("socket num %ld", get_sock_num(sock));
965 err = tcp_shutdown((struct tcp_pcb *) sock->pcb, 0, 1);
967 switch (err) {
968 case ERR_OK:
969 sock_reply(sock, OK);
970 break;
971 case ERR_CONN:
972 sock_reply(sock, ENOTCONN);
973 break;
974 default:
975 sock_reply(sock, EGENERIC);
979 static void tcp_op_get_cookie(struct socket * sock, message * m)
981 tcp_cookie_t cookie;
982 unsigned sock_num;
984 assert(sizeof(cookie) >= sizeof(sock));
986 sock_num = get_sock_num(sock);
987 memcpy(&cookie, &sock_num, sizeof(sock_num));
989 if (copy_to_user(m->m_source, &cookie, sizeof(sock),
990 (cp_grant_id_t) m->IO_GRANT, 0) == OK)
991 sock_reply(sock, OK);
992 else
993 sock_reply(sock, EFAULT);
996 static void tcp_get_opt(struct socket * sock, message * m)
998 int err;
999 nwio_tcpopt_t tcpopt;
1000 struct tcp_pcb * pcb = (struct tcp_pcb *) sock->pcb;
1002 debug_tcp_print("socket num %ld", get_sock_num(sock));
1004 assert(pcb);
1006 if ((unsigned) m->COUNT < sizeof(tcpopt)) {
1007 sock_reply(sock, EINVAL);
1008 return;
1011 /* FIXME : not used by the userspace library */
1012 tcpopt.nwto_flags = 0;
1014 err = copy_to_user(m->m_source, &tcpopt, sizeof(tcpopt),
1015 (cp_grant_id_t) m->IO_GRANT, 0);
1017 if (err != OK)
1018 sock_reply(sock, err);
1020 sock_reply(sock, OK);
1023 static void tcp_set_opt(struct socket * sock, message * m)
1025 int err;
1026 nwio_tcpopt_t tcpopt;
1027 struct tcp_pcb * pcb = (struct tcp_pcb *) sock->pcb;
1029 debug_tcp_print("socket num %ld", get_sock_num(sock));
1031 assert(pcb);
1033 err = copy_from_user(m->m_source, &tcpopt, sizeof(tcpopt),
1034 (cp_grant_id_t) m->IO_GRANT, 0);
1036 if (err != OK)
1037 sock_reply(sock, err);
1039 /* FIXME : The userspace library does not use this */
1041 sock_reply(sock, OK);
1044 static void tcp_op_ioctl(struct socket * sock, message * m, __unused int blk)
1046 if (!sock->pcb) {
1047 sock_reply(sock, ENOTCONN);
1048 return;
1051 debug_tcp_print("socket num %ld req %c %d %d",
1052 get_sock_num(sock),
1053 (m->REQUEST >> 8) & 0xff,
1054 m->REQUEST & 0xff,
1055 (m->REQUEST >> 16) & _IOCPARM_MASK);
1057 switch (m->REQUEST) {
1058 case NWIOGTCPCONF:
1059 tcp_get_conf(sock, m);
1060 break;
1061 case NWIOSTCPCONF:
1062 tcp_set_conf(sock, m);
1063 break;
1064 case NWIOTCPCONN:
1065 tcp_op_connect(sock);
1066 break;
1067 case NWIOTCPLISTENQ:
1068 tcp_op_listen(sock, m);
1069 break;
1070 case NWIOGTCPCOOKIE:
1071 tcp_op_get_cookie(sock, m);
1072 break;
1073 case NWIOTCPACCEPTTO:
1074 tcp_op_accept(sock, m);
1075 break;
1076 case NWIOTCPSHUTDOWN:
1077 tcp_op_shutdown_tx(sock);
1078 break;
1079 case NWIOGTCPOPT:
1080 tcp_get_opt(sock, m);
1081 break;
1082 case NWIOSTCPOPT:
1083 tcp_set_opt(sock, m);
1084 break;
1085 default:
1086 sock_reply(sock, EBADIOCTL);
1087 return;
1091 static void tcp_op_select(struct socket * sock, __unused message * m)
1093 int retsel = 0, sel;
1095 sel = m->USER_ENDPT;
1096 debug_tcp_print("socket num %ld 0x%x", get_sock_num(sock), sel);
1098 /* in this case any operation would block, no error */
1099 if (sock->flags & SOCK_FLG_OP_PENDING) {
1100 debug_tcp_print("SOCK_FLG_OP_PENDING");
1101 if (sel & SEL_NOTIFY) {
1102 if (sel & SEL_RD) {
1103 sock->flags |= SOCK_FLG_SEL_READ;
1104 debug_tcp_print("monitor read");
1106 if (sel & SEL_WR) {
1107 sock->flags |= SOCK_FLG_SEL_WRITE;
1108 debug_tcp_print("monitor write");
1110 if (sel & SEL_ERR)
1111 sock->flags |= SOCK_FLG_SEL_ERROR;
1113 sock_reply_select(sock, 0);
1114 return;
1117 if (sel & SEL_RD) {
1119 * If recv_head is not NULL we can either read or accept a
1120 * connection which is the same for select()
1122 if (sock->pcb) {
1123 if (sock->recv_head &&
1124 !(sock->flags & SOCK_FLG_OP_WRITING))
1125 retsel |= SEL_RD;
1126 else if (!(sock->flags & SOCK_FLG_OP_LISTENING) &&
1127 ((struct tcp_pcb *) sock->pcb)->state != ESTABLISHED)
1128 retsel |= SEL_RD;
1129 else if (sel & SEL_NOTIFY) {
1130 sock->flags |= SOCK_FLG_SEL_READ;
1131 debug_tcp_print("monitor read");
1133 } else
1134 retsel |= SEL_RD; /* not connected read does not block */
1136 if (sel & SEL_WR) {
1137 if (sock->pcb) {
1138 if (((struct tcp_pcb *) sock->pcb)->state == ESTABLISHED)
1139 retsel |= SEL_WR;
1140 else if (sel & SEL_NOTIFY) {
1141 sock->flags |= SOCK_FLG_SEL_WRITE;
1142 debug_tcp_print("monitor write");
1144 } else
1145 retsel |= SEL_WR; /* not connected write does not block */
1148 if (retsel & SEL_RD) {
1149 debug_tcp_print("read won't block");
1151 if (retsel & SEL_WR) {
1152 debug_tcp_print("write won't block");
1155 /* we only monitor if errors will happen in the future */
1156 if (sel & SEL_ERR && sel & SEL_NOTIFY)
1157 sock->flags |= SOCK_FLG_SEL_ERROR;
1159 sock_reply_select(sock, retsel);
1162 static void tcp_op_select_reply(struct socket * sock, message * m)
1164 assert(sock->select_ep != NONE);
1165 debug_tcp_print("socket num %ld", get_sock_num(sock));
1168 if (sock->flags & SOCK_FLG_OP_PENDING) {
1169 debug_tcp_print("WARNING socket still blocking!");
1170 return;
1173 if (sock->flags & SOCK_FLG_SEL_READ) {
1174 if (sock->pcb == NULL || (sock->recv_head &&
1175 !(sock->flags & SOCK_FLG_OP_WRITING)) ||
1176 (!(sock->flags & SOCK_FLG_OP_LISTENING) &&
1177 ((struct tcp_pcb *) sock->pcb)->state !=
1178 ESTABLISHED)) {
1179 m->DEV_SEL_OPS |= SEL_RD;
1180 debug_tcp_print("read won't block");
1184 if (sock->flags & SOCK_FLG_SEL_WRITE &&
1185 (sock->pcb == NULL ||
1186 ((struct tcp_pcb *) sock->pcb)->state ==
1187 ESTABLISHED)) {
1188 m->DEV_SEL_OPS |= SEL_WR;
1189 debug_tcp_print("write won't block");
1192 if (m->DEV_SEL_OPS)
1193 sock->flags &= ~(SOCK_FLG_SEL_WRITE | SOCK_FLG_SEL_READ |
1194 SOCK_FLG_SEL_ERROR);
1197 struct sock_ops sock_tcp_ops = {
1198 .open = tcp_op_open,
1199 .close = tcp_op_close,
1200 .read = tcp_op_read,
1201 .write = tcp_op_write,
1202 .ioctl = tcp_op_ioctl,
1203 .select = tcp_op_select,
1204 .select_reply = tcp_op_select_reply