3 * Copyright (C) 2008 Tomas 'ZeXx86' Jedrzejek (zexx86@zexos.org)
4 * Copyright (C) 2009 Tomas 'ZeXx86' Jedrzejek (zexx86@zexos.org)
5 * Copyright (C) 2010 Tomas 'ZeXx86' Jedrzejek (zexx86@zexos.org)
7 * This program is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation, either version 3 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program. If not, see <http://www.gnu.org/licenses/>.
28 #include <net/packet.h>
31 #include <net/socket.h>
36 /* Mutex for socket function */
37 MUTEX_CREATE (mutex_tcp_accept
);
38 MUTEX_CREATE (mutex_tcp_read_cache
);
40 extern netif_t netif_list
;
42 proto_tcp_conn_t proto_tcp_conn_list
;
43 proto_tcp_backlog_t proto_tcp_backlog_list
;
45 static unsigned short proto_tcp_dup
;
46 static unsigned proto_tcp_seq
;
47 static proto_ip_t proto_ip_prealloc
;
48 static proto_tcp_t proto_tcp_prealloc
;
49 static packet_t packet_prealloc
;
50 static char buf_tcp_prealloc
[NET_PACKET_MTU
+ sizeof (proto_tcp_t
) + 1];
53 proto_tcp_conn_t
*net_proto_tcp_conn_check (net_ipv4 ip_source
, net_port port_source
, net_ipv4 ip_dest
, net_port port_dest
, unsigned char *ret
);
54 int net_proto_tcp_conn_add (fd_t
*fd
);
55 int net_proto_tcp_conn_set (proto_tcp_conn_t
*conn
, netif_t
*eth
, net_port port_source
, net_ipv4 ip_dest
, net_port port_dest
);
56 int net_proto_tcp_conn_estabilish (proto_tcp_conn_t
*conn
, netif_t
*eth
, net_ipv4 ip_dest
, net_port port_dest
);
57 int net_proto_tcp_conn_estabilish_reply (proto_tcp_conn_t
*conn
, proto_ip_t
*ip_old
, proto_tcp_t
*tcp_old
);
58 int net_proto_tcp_read_cache (proto_tcp_conn_t
*conn
, char *data
, unsigned len
);
59 int net_proto_tcp_read_ok (proto_tcp_conn_t
*conn
, proto_ip_t
*ip_old
, proto_tcp_t
*tcp_old
, unsigned len
);
60 int net_proto_tcp_write (netif_t
*eth
, net_ipv4 dest
, proto_tcp_t
*tcp
, char *data
, unsigned len
);
61 int net_proto_tcp_write_data (proto_tcp_conn_t
*conn
, char *data
, unsigned len
);
62 int net_proto_tcp_write_data_ok (proto_tcp_conn_t
*conn
, proto_ip_t
*ip_old
, proto_tcp_t
*tcp_old
);
63 int net_proto_tcp_conn_disconnected (proto_tcp_conn_t
*conn
, proto_ip_t
*ip_old
, proto_tcp_t
*tcp_old
);
64 int net_proto_tcp_conn_close (proto_tcp_conn_t
*conn
);
65 unsigned net_proto_tcp_conn_del (proto_tcp_conn_t
*conn
);
66 proto_tcp_conn_t
*net_proto_tcp_conn_find (int fd
);
67 int net_proto_tcp_backlog_add (proto_tcp_conn_t
*conn
, net_ipv4 ip
, net_port port
, unsigned seq
);
68 int net_proto_tcp_conn_invite (proto_tcp_conn_t
*conn
, net_ipv4 ip
, net_port port
, unsigned seq
);
71 * User-friendly socket functions
73 int net_proto_tcp_socket (fd_t
*fd
)
75 return net_proto_tcp_conn_add (fd
);
78 extern unsigned long timer_ticks
;
79 int net_proto_tcp_connect (int fd
, sockaddr_in
*addr
)
83 proto_tcp_conn_t
*conn
= net_proto_tcp_conn_find (fd
);
89 for (netif
= netif_list
.next
; netif
!= &netif_list
; netif
= netif
->next
) {
90 ret
= net_proto_tcp_conn_estabilish (conn
, netif
, addr
->sin_addr
, addr
->sin_port
);
92 unsigned long stime
= timer_ticks
;
95 if (!(conn
->flags
& O_NONBLOCK
)) {
103 if ((stime
+8000) < timer_ticks
)
106 if (conn
->state
== PROTO_TCP_CONN_STATE_ESTABILISHED
)
109 /* when connection cant be accepted succefully first time, try it again */
110 if (conn
->state
== PROTO_TCP_CONN_STATE_ESTABILISHERROR
) {
111 ret
= net_proto_tcp_conn_estabilish (conn
, netif
, addr
->sin_addr
, addr
->sin_port
);
112 conn
->state
= PROTO_TCP_CONN_STATE_ESTABILISH
;
116 /* non-blocking mode */
125 int net_proto_tcp_send (int fd
, char *msg
, unsigned size
)
127 proto_tcp_conn_t
*conn
= net_proto_tcp_conn_find (fd
);
134 unsigned mtu_tcp
= NET_PACKET_MTU
- sizeof (proto_tcp_t
) - sizeof (net_ipv4
) - 16;
137 if (size
> mtu_tcp
) {
138 int r
= net_proto_tcp_send (fd
, msg
, mtu_tcp
);
149 int ret
= net_proto_tcp_write_data (conn
, msg
, size
);
152 unsigned long stime
= timer_ticks
;
155 if (!(conn
->flags
& O_NONBLOCK
)) {
156 while (conn
->state
!= PROTO_TCP_CONN_STATE_READY
) {
158 if ((stime
+350) < timer_ticks
)
165 /* non-blocking mode */
168 while (conn
->state
!= PROTO_TCP_CONN_STATE_READY
) {
170 if ((stime
+100) < timer_ticks
)
182 int net_proto_tcp_recv (int fd
, char *msg
, unsigned size
)
184 proto_tcp_conn_t
*conn
= net_proto_tcp_conn_find (fd
);
191 //kprintf ("recv () - %d\n", fd);
194 if (!(conn
->flags
& O_NONBLOCK
)) {
195 unsigned long stime
= timer_ticks
;
197 while (!conn
->len
/* || conn->state != PROTO_TCP_CONN_STATE_READY*/) {
198 if ((stime
+10000) < timer_ticks
)
201 if (conn
->state
== PROTO_TCP_CONN_STATE_CLOSE
) {
202 if (net_proto_tcp_conn_del (conn
));
209 if (conn
->state
== PROTO_TCP_CONN_STATE_CLOSE
) {
210 if (net_proto_tcp_conn_del (conn
));
218 if ((conn
->len
-conn
->offset
) > size
) {
219 memcpy (msg
, conn
->data
+conn
->offset
, size
);
220 //printf ("msg11: %d %d\n", conn->offset, size);
221 conn
->offset
+= size
;
225 ret
= conn
->len
-conn
->offset
;
227 memcpy (msg
, conn
->data
+conn
->offset
, conn
->len
-conn
->offset
);
228 //printf ("msg22: %d %d %d\n", conn->offset, size, conn->len);
235 //kprintf ("recv () - %d -- DATA: %d : %d\n", fd, ret, size);
240 int net_proto_tcp_close (int fd
)
242 proto_tcp_conn_t
*conn
= net_proto_tcp_conn_find (fd
);
247 if (conn
->state
== PROTO_TCP_CONN_STATE_DISCONNECTED
)
250 return net_proto_tcp_conn_close (conn
);
253 int net_proto_tcp_fcntl (int fd
, int cmd
, long arg
)
255 proto_tcp_conn_t
*conn
= net_proto_tcp_conn_find (fd
);
271 int net_proto_tcp_bind (int fd
, sockaddr_in
*addr
, socklen_t len
)
273 proto_tcp_conn_t
*conn
= net_proto_tcp_conn_find (fd
);
279 for (netif
= netif_list
.next
; netif
!= &netif_list
; netif
= netif
->next
) {
280 net_proto_tcp_conn_set (conn
, netif
, addr
->sin_port
, 0, 0);
288 int net_proto_tcp_listen (int fd
, int backlog
)
290 proto_tcp_conn_t
*conn
= net_proto_tcp_conn_find (fd
);
298 int net_proto_tcp_accept (int fd
, sockaddr_in
*addr
, socklen_t
*addrlen
)
300 proto_tcp_conn_t
*conn
= net_proto_tcp_conn_find (fd
);
307 proto_tcp_backlog_t
*backlog
= 0;
310 if (!(conn
->flags
& O_NONBLOCK
)) {
312 for (backlog
= proto_tcp_backlog_list
.next
; backlog
!= &proto_tcp_backlog_list
; backlog
= backlog
->next
) {
313 if (backlog
->conn
== conn
) {
322 /* non-blocking mode */
323 for (backlog
= proto_tcp_backlog_list
.next
; backlog
!= &proto_tcp_backlog_list
; backlog
= backlog
->next
) {
324 if (backlog
->conn
== conn
) {
331 //printf ("accept ()\n");
336 net_ipv4 ip
= backlog
->ip
;
337 net_port port
= backlog
->port
;
338 unsigned seq
= backlog
->seq
;
340 int ret
= net_proto_tcp_conn_invite (conn
, ip
, port
, seq
);
342 /* remove from queue accepted connection */
343 backlog
->next
->prev
= backlog
->prev
;
344 backlog
->prev
->next
= backlog
->next
;
351 fd_t
*fd_new
= fd_create (FD_SOCK
);
356 net_proto_tcp_conn_add (fd_new
);
358 proto_tcp_conn_t
*conn_new
= net_proto_tcp_conn_find (fd_new
->id
);
363 net_proto_tcp_conn_set (conn_new
, conn
->netif
, conn
->port_source
, conn
->netif
->ip
, port
);
365 conn_new
->ip_dest
= ip
;
368 addr
->sin_port
= port
;
369 addr
->sin_family
= AF_INET
;
372 unsigned long stime
= timer_ticks
;
373 while (conn_new
->state
!= PROTO_TCP_CONN_STATE_READY
) {
374 if ((stime
+10) < timer_ticks
)
383 int net_proto_tcp_select (int readfd
, int writefd
, int exceptfd
)
394 proto_tcp_conn_t
*conn
= net_proto_tcp_conn_find (fd
);
399 /* check for incoming connections */
401 proto_tcp_backlog_t
*backlog
= 0;
403 for (backlog
= proto_tcp_backlog_list
.next
; backlog
!= &proto_tcp_backlog_list
; backlog
= backlog
->next
) {
404 if (backlog
->conn
== conn
)
411 /* Is socket closed ? */
412 if (conn
->state
== PROTO_TCP_CONN_STATE_CLOSE
)
415 /* Are some data available ? */
423 * Hardcore code - syn, ack, psh, fin, etc :P
425 unsigned net_proto_tcp_handler (packet_t
*packet
, proto_ip_t
*ip
, char *buf
, unsigned len
)
427 proto_tcp_t
*tcp
= (proto_tcp_t
*) buf
;
429 unsigned char ret
= 0;
431 /* First check ip address and ports, that we want this data */
432 proto_tcp_conn_t
*conn
= net_proto_tcp_conn_check (ip
->ip_dest
, tcp
->port_dest
, ip
->ip_source
, tcp
->port_source
, &ret
);
434 if (!conn
&& ret
== 0)
437 //printf ("tcp->flags: 0x%x, ret: %d, conn: 0x%x, fd: %d\n", tcp->flags, ret, conn, conn->fd);
439 /* connection from client before accept () */
441 /* client want connect to our server */
442 if (tcp
->flags
== 0x02) {
443 mutex_lock (&mutex_tcp_accept
);
445 unsigned ret
= net_proto_tcp_backlog_add (conn
, ip
->ip_source
, tcp
->port_source
, tcp
->seq
);
447 mutex_unlock (&mutex_tcp_accept
);
455 unsigned data_cache
= 0;
458 if (tcp
->flags
& 0x08) {
459 /* needed for calculate real offset from 4bit number */
460 unsigned offset
= tcp
->data_offset
* 4;
462 /* now calculate accurate length of tcp _data_ */
463 unsigned size
= swap16 (ip
->total_len
) - (offset
+ (ip
->head_len
*4));
464 //kprintf (">>>> %d : %d : %d\n", offset, size, len);
465 //mutex_lock (&mutex_tcp_read_cache);
466 net_proto_tcp_read_cache (conn
, buf
+offset
, size
);
467 //mutex_unlock (&mutex_tcp_read_cache);
469 net_proto_tcp_read_ok (conn
, ip
, tcp
, size
);
474 /* sended data was delivered succefully / ACK */
475 if (tcp
->flags
& 0x10) {
476 /* HACK: It is interesting, that no push flag, and there could be some data to read */
478 /* needed for calculate real offset from 4bit number */
479 unsigned offset
= tcp
->data_offset
* 4;
481 /* now calculate accurate length of tcp _data_ */
482 unsigned size
= swap16 (ip
->total_len
) - (offset
+ (ip
->head_len
*4));
484 /* there are data for read */
486 /* data was cached, so no need cache it again */
488 //kprintf (">>>>2 %d : %d : %d\n", offset, size, len);
489 mutex_lock (&mutex_tcp_read_cache
);
490 net_proto_tcp_read_cache (conn
, buf
+offset
, size
);
491 mutex_unlock (&mutex_tcp_read_cache
);
493 net_proto_tcp_read_ok (conn
, ip
, tcp
, size
);
496 /* when data are'nt available, lets normal work - acknowledgement */
497 if (conn
->state
== PROTO_TCP_CONN_STATE_ESTABILISH
) {
498 conn
->state
= PROTO_TCP_CONN_STATE_ESTABILISHERROR
;
499 net_proto_tcp_write_data_ok (conn
, ip
, tcp
);
501 net_proto_tcp_write_data_ok (conn
, ip
, tcp
);
505 /* connection estabilish respond */
506 if (tcp
->flags
== 0x12) {
507 return net_proto_tcp_conn_estabilish_reply (conn
, ip
, tcp
);
510 /* another side close connection */
511 if (tcp
->flags
& 0x01) {
512 DPRINT (DBG_NET
| DBG_SOCKET
| DBG_TCP
, "TCP -> fd %d connection closed by remote host", conn
->fd
);
513 net_proto_tcp_conn_disconnected (conn
, ip
, tcp
); // FIXME: problem in server with hangind the whole program
516 /* another side close connection */
517 if (tcp
->flags
& 0x04) {
518 DPRINT (DBG_NET
| DBG_SOCKET
| DBG_TCP
, "TCP -> fd %d connection reseted by peer", conn
->fd
);
519 net_proto_tcp_conn_disconnected (conn
, ip
, tcp
);
525 int net_proto_tcp_read_cache (proto_tcp_conn_t
*conn
, char *data
, unsigned len
)
527 if (!data
|| !conn
|| !len
)
531 conn
->data
= (char *) kmalloc (sizeof (char) * (len
+ 1));
533 memcpy (conn
->data
, data
, len
);
535 char *newdata
= (char *) kmalloc (sizeof (char) * (conn
->len
+ len
+ 1));
540 memcpy (newdata
, conn
->data
, conn
->len
);
541 memcpy (newdata
+conn
->len
, data
, len
);
545 conn
->data
= newdata
;
551 //kprintf ("DATA: %d - #'%s'#\n", len, data);
555 conn
->data
[conn
->len
] = '\0';
560 int net_proto_tcp_read_ok (proto_tcp_conn_t
*conn
, proto_ip_t
*ip_old
, proto_tcp_t
*tcp_old
, unsigned len
)
562 if (!ip_old
|| !tcp_old
|| !conn
)
565 proto_tcp_t
*tcp
= (proto_tcp_t
*) kmalloc (sizeof (proto_tcp_t
));
570 tcp
->port_source
= conn
->port_source
; // increase client port too
571 tcp
->port_dest
= conn
->port_dest
;
573 tcp
->seq
= tcp_old
->ack
;
575 /* this small thing did bad work when e.g. 10 10 10 fe get to calculation,
576 it returns 10 10 10 08, no 10 10 11 08 */
577 unsigned seq
= swap32 (tcp_old
->seq
);
580 tcp
->ack
= swap32 (seq
);
583 tcp
->data_offset
= 5;
585 tcp
->window
= tcp_old
->window
+ swap16 (64);
588 int ret
= net_proto_tcp_write (conn
->netif
, conn
->ip_dest
, tcp
, 0, 0);
590 /*if (proto_tcp_dup == tcp_old->checksum) {
591 printf ("Duplicated packet :)");
596 //printf ("read_ok: seq: 0x%x | ack: 0x%x\n", conn->seq, conn->ack);
598 conn
->seq
= tcp
->ack
;
599 conn
->ack
= tcp
->seq
;
601 //printf ("read_ok2: seq: 0x%x | ack: 0x%x\n", conn->seq, conn->ack);
603 proto_tcp_dup
= tcp_old
->checksum
;
613 int net_proto_tcp_write (netif_t
*eth
, net_ipv4 dest
, proto_tcp_t
*tcp
, char *data
, unsigned len
)
623 unsigned get
= arp_cache_get (dest
, &mac_dest
);
626 arp_send_request (eth
, dest
);
629 /* 100ms for waiting on ARP reply */
631 get
= arp_cache_get (dest
, &mac_dest
);
636 /* TODO: make better waiting for ARP reply */
649 packet_t
*packet
= &packet_prealloc
;
654 memcpy (&packet
->mac_source
, eth
->dev
->dev_addr
, 6);
655 memcpy (&packet
->mac_dest
, mac_dest
, 6);
656 packet
->type
= NET_PACKET_TYPE_IPV4
;
659 proto_ip_t
*ip
= &proto_ip_prealloc
;
664 /* there are some fixed values - yeah it is horrible */
672 ip
->proto
= NET_PROTO_IP_TYPE_TCP
;
673 ip
->ip_source
= eth
->ip
;
676 unsigned l
= (tcp
->data_offset
*4);
678 /* calculate total length of packet (tcp/ip) */
679 ip
->total_len
= swap16 (l
+sizeof (proto_tcp_t
)+len
);
681 if (len
+l
> NET_PACKET_MTU
+ sizeof (proto_tcp_t
)) {
682 DPRINT (DBG_NET
| DBG_SOCKET
| DBG_TCP
, "TCP -> data lenght is exceed: %d/%d bytes", len
+l
, NET_PACKET_MTU
+ sizeof (proto_tcp_t
) + 1);
686 char *buf_tcp
= (char *) &buf_tcp_prealloc
; //(char *) kmalloc ((len+l+1) * sizeof (char));
691 memcpy (buf_tcp
, (char *) tcp
, l
);
694 memcpy (buf_tcp
+l
, data
, len
);
696 // buf_tcp[l+len] = '\0';
698 /* calculate checksum and put it to tcp header */
699 proto_tcp_t
*tcp_
= (proto_tcp_t
*) buf_tcp
;
701 tcp_
->checksum
= checksum16_tcp (eth
->ip
, dest
, buf_tcp
, l
+len
);
703 /* send tcp header+data to ip layer */
704 unsigned ret
= net_proto_ip_send (eth
, packet
, ip
, (char *) buf_tcp
, l
+len
);
711 int net_proto_tcp_write_data (proto_tcp_conn_t
*conn
, char *data
, unsigned len
)
713 if (!conn
|| !len
|| !data
)
716 proto_tcp_t
*tcp
= &proto_tcp_prealloc
;
721 tcp
->port_source
= conn
->port_source
;
722 tcp
->port_dest
= conn
->port_dest
;
724 unsigned seq
= swap32 (proto_tcp_seq
);
727 //tcp->ack = swap32 (seq);
729 proto_tcp_seq
= swap32 (seq
);
732 tcp
->seq
= conn
->seq
;
733 tcp
->ack
= conn
->ack
;
735 tcp
->seq
= conn
->ack
;
736 tcp
->ack
= conn
->seq
;
741 // printf ("TCP -> seq: 0x%x | ack: 0x%x | proto_seq: 0x%x\n", tcp->seq, tcp->ack, proto_tcp_seq);
744 tcp
->data_offset
= 5;
746 tcp
->window
= swap16 (32768);
749 int ret
= net_proto_tcp_write (conn
->netif
, conn
->ip_dest
, tcp
, data
, len
);
752 conn
->state
= PROTO_TCP_CONN_STATE_WAIT
;
757 int net_proto_tcp_write_data_ok (proto_tcp_conn_t
*conn
, proto_ip_t
*ip_old
, proto_tcp_t
*tcp_old
)
759 if (!ip_old
|| !tcp_old
|| !conn
)
762 /* cross - because we change now sides :) */
763 conn
->seq
= tcp_old
->ack
;
764 conn
->ack
= tcp_old
->seq
;
766 // printf ("data_ok: seq: 0x%x | ack: 0x%x\n", tcp_old->ack, tcp_old->seq);
768 conn
->state
= PROTO_TCP_CONN_STATE_READY
;
773 /* try connect to server */
774 int net_proto_tcp_conn_estabilish (proto_tcp_conn_t
*conn
, netif_t
*eth
, net_ipv4 ip_dest
, net_port port_dest
)
779 proto_tcp_t
*tcp
= (proto_tcp_t
*) kmalloc (sizeof (proto_tcp_t
));
784 tcp
->port_source
= swap16 (netif_port_get ()); // increase client port too
785 tcp
->port_dest
= port_dest
;
787 /* setup new connection */
788 net_proto_tcp_conn_set (conn
, eth
, tcp
->port_source
, ip_dest
, tcp
->port_dest
);
790 tcp
->seq
= conn
->seq
;
791 tcp
->ack
= conn
->ack
;
794 tcp
->data_offset
= 5;
796 tcp
->window
= swap16 (32792);
799 int ret
= net_proto_tcp_write (eth
, ip_dest
, tcp
, 0, 0);
804 net_proto_tcp_conn_del (conn
);
811 int net_proto_tcp_conn_estabilish_reply (proto_tcp_conn_t
*conn
, proto_ip_t
*ip_old
, proto_tcp_t
*tcp_old
)
813 if (!ip_old
|| !tcp_old
|| !conn
)
816 proto_tcp_t
*tcp
= (proto_tcp_t
*) kmalloc (sizeof (proto_tcp_t
));
821 tcp
->port_source
= conn
->port_source
; // increase client port too
822 tcp
->port_dest
= conn
->port_dest
;
824 tcp
->seq
= tcp_old
->ack
;
825 tcp
->ack
= tcp_old
->seq
+ swap32 (1);
828 tcp
->data_offset
= 5;
830 tcp
->window
= tcp_old
->window
+ swap16 (64);
833 int ret
= net_proto_tcp_write (conn
->netif
, conn
->ip_dest
, tcp
, 0, 0);
836 conn
->seq
= tcp
->seq
;
837 conn
->ack
= tcp
->ack
;
838 conn
->state
= PROTO_TCP_CONN_STATE_ESTABILISHED
;
840 DPRINT (DBG_NET
| DBG_SOCKET
| DBG_TCP
, "TCP -> fd %d connected to server succefully\n", conn
->fd
);
848 int net_proto_tcp_conn_disconnected (proto_tcp_conn_t
*conn
, proto_ip_t
*ip_old
, proto_tcp_t
*tcp_old
)
850 if (!ip_old
|| !tcp_old
|| !conn
)
853 if (conn
->state
== PROTO_TCP_CONN_STATE_CLOSE
)
854 return net_proto_tcp_conn_del (conn
);
856 proto_tcp_t
*tcp
= (proto_tcp_t
*) kmalloc (sizeof (proto_tcp_t
));
861 tcp
->port_source
= conn
->port_source
; // increase client port too
862 tcp
->port_dest
= conn
->port_dest
;
864 tcp
->seq
= tcp_old
->ack
;
865 tcp
->ack
= tcp_old
->seq
+ swap32 (1);
868 tcp
->data_offset
= 5;
870 tcp
->window
= tcp_old
->window
+ swap16 (64);
873 int ret
= net_proto_tcp_write (conn
->netif
, conn
->ip_dest
, tcp
, 0, 0);
878 conn
->state
= PROTO_TCP_CONN_STATE_CLOSE
; //ret = net_proto_tcp_conn_del (conn);
885 int net_proto_tcp_conn_close (proto_tcp_conn_t
*conn
)
887 return 0; /* FIXME: close () is faster then send () sometime :-B */
892 if (conn
->state
== PROTO_TCP_CONN_STATE_CLOSE
)
895 proto_tcp_t
*tcp
= (proto_tcp_t
*) kmalloc (sizeof (proto_tcp_t
));
900 tcp
->port_source
= conn
->port_source
; // increase client port too
901 tcp
->port_dest
= conn
->port_dest
;
903 tcp
->seq
= conn
->seq
;
904 tcp
->ack
= conn
->ack
;
907 tcp
->data_offset
= 5;
909 tcp
->window
= swap16 (32832);
912 int ret
= net_proto_tcp_write (conn
->netif
, conn
->ip_dest
, tcp
, 0, 0);
917 conn
->state
= PROTO_TCP_CONN_STATE_CLOSE
;
922 /* client wants to connect */
923 net_proto_tcp_conn_invite (proto_tcp_conn_t
*conn
, net_ipv4 ip
, net_port port
, unsigned seq
)
928 proto_tcp_t
*tcp
= (proto_tcp_t
*) kmalloc (sizeof (proto_tcp_t
));
933 tcp
->port_source
= conn
->port_source
;
934 tcp
->port_dest
= port
;
936 tcp
->seq
= proto_tcp_seq
++;
937 tcp
->ack
= seq
+ swap32 (1);
940 tcp
->data_offset
= 5;
942 tcp
->window
= swap16 (5816);
945 int ret
= net_proto_tcp_write (conn
->netif
, ip
, tcp
, 0, 0);
950 conn
->state
= PROTO_TCP_CONN_STATE_READY
;
958 /* Create new TCP connection */
959 int net_proto_tcp_conn_add (fd_t
*fd
)
961 proto_tcp_conn_t
*conn
;
963 /* alloc and init context */
964 conn
= (proto_tcp_conn_t
*) kmalloc (sizeof (proto_tcp_conn_t
));
971 memset (conn
, 0, sizeof (proto_tcp_conn_t
));
981 conn
->next
= &proto_tcp_conn_list
;
982 conn
->prev
= proto_tcp_conn_list
.prev
;
983 conn
->prev
->next
= conn
;
984 conn
->next
->prev
= conn
;
989 /* Setup new connection */
990 int net_proto_tcp_conn_set (proto_tcp_conn_t
*conn
, netif_t
*eth
, net_port port_source
, net_ipv4 ip_dest
, net_port port_dest
)
995 conn
->ip_source
= eth
->ip
;
996 conn
->ip_dest
= ip_dest
;
998 conn
->port_source
= port_source
;
999 conn
->port_dest
= port_dest
;
1001 proto_tcp_seq
+= swap32 (1);
1003 conn
->seq
= proto_tcp_seq
++;
1006 conn
->state
= PROTO_TCP_CONN_STATE_ESTABILISH
;
1017 /* Delete existing connection from list */
1018 unsigned net_proto_tcp_conn_del (proto_tcp_conn_t
*conn
)
1023 conn
->state
= PROTO_TCP_CONN_STATE_DISCONNECTED
;
1030 conn
->next
->prev
= conn
->prev
;
1031 conn
->prev
->next
= conn
->next
;
1038 proto_tcp_conn_t
*net_proto_tcp_conn_check (net_ipv4 ip_source
, net_port port_source
, net_ipv4 ip_dest
, net_port port_dest
, unsigned char *ret
)
1041 proto_tcp_conn_t
*conn
= NULL
;
1042 proto_tcp_conn_t
*conn_ret
= NULL
;
1043 //printf ("-------------------------\n");
1044 for (conn
= proto_tcp_conn_list
.next
; conn
!= &proto_tcp_conn_list
; conn
= conn
->next
) {
1046 net_proto_ip_print (conn->ip_source);
1048 net_proto_ip_print (ip_source);
1050 net_proto_ip_print (conn->ip_dest);
1052 net_proto_ip_print (ip_dest);
1053 printf ("\nporty: %d / %d\n", swap16 (conn->port_source), swap16 (port_source));
1054 printf ("porty2: %d / %d\n", swap16 (conn->port_dest), swap16 (port_dest));*/
1056 if (conn
->ip_source
== ip_source
&& conn
->port_source
== port_source
) {
1057 if (conn
->ip_dest
== ip_dest
&& conn
->port_dest
== port_dest
) {
1069 if (!conn_ret
->bind
) {
1072 for (conn
= proto_tcp_conn_list
.next
; conn
!= &proto_tcp_conn_list
; conn
= conn
->next
) {
1074 if (conn
->ip_source
== ip_source
&& conn
->port_source
== port_source
)
1083 proto_tcp_conn_t
*net_proto_tcp_conn_find (int fd
)
1085 proto_tcp_conn_t
*conn
= NULL
;
1086 for (conn
= proto_tcp_conn_list
.next
; conn
!= &proto_tcp_conn_list
; conn
= conn
->next
) {
1094 /* Create new TCP backlog stamp */
1095 int net_proto_tcp_backlog_add (proto_tcp_conn_t
*conn
, net_ipv4 ip
, net_port port
, unsigned seq
)
1100 proto_tcp_backlog_t
*backlog
;
1102 /* alloc and init context */
1103 backlog
= (proto_tcp_backlog_t
*) kmalloc (sizeof (proto_tcp_backlog_t
));
1108 backlog
->conn
= conn
;
1110 backlog
->port
= port
;
1114 backlog
->next
= &proto_tcp_backlog_list
;
1115 backlog
->prev
= proto_tcp_backlog_list
.prev
;
1116 backlog
->prev
->next
= backlog
;
1117 backlog
->next
->prev
= backlog
;
1122 /* init of tcp protocol */
1123 unsigned init_net_proto_tcp ()
1125 proto_tcp_conn_list
.next
= &proto_tcp_conn_list
;
1126 proto_tcp_conn_list
.prev
= &proto_tcp_conn_list
;
1128 proto_tcp_backlog_list
.next
= &proto_tcp_backlog_list
;
1129 proto_tcp_backlog_list
.prev
= &proto_tcp_backlog_list
;
1131 proto_tcp_dup
= 0x0;
1132 proto_tcp_seq
= 0x1;