Subversion Repositories Kolibri OS

Rev

Rev 1257 | Go to most recent revision | Blame | Last modification | View Log | Download | RSS feed

  1. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  2. ;;                                                                 ;;
  3. ;; Copyright (C) KolibriOS team 2004-2009. All rights reserved.    ;;
  4. ;; Distributed under terms of the GNU General Public License       ;;
  5. ;;                                                                 ;;
  6. ;;  TCP.INC                                                        ;;
  7. ;;                                                                 ;;
  8. ;;  Part of the tcp/ip network stack for KolibriOS                 ;;
  9. ;;                                                                 ;;
  10. ;;    Written by hidnplayr@kolibrios.org                           ;;
  11. ;;                                                                 ;;
  12. ;;          GNU GENERAL PUBLIC LICENSE                             ;;
  13. ;;             Version 2, June 1991                                ;;
  14. ;;                                                                 ;;
  15. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  16.  
  17.  
  18. $Revision: 1274 $
  19.  
  20. TCP_RETRIES             equ 5           ; Number of times to resend a Packet
  21. TCP_PACKET_TTL          equ 50          ; resend if not replied to in 1/100 s
  22. TCP_SOCKET_TTL          equ 10          ; # of secs to wait before closing socket
  23. TCP_QUEUE_SIZE          equ 16
  24.  
  25.  
  26. struct  TCP_Packet
  27.         .SourcePort             dw ?
  28.         .DestinationPort        dw ?
  29.         .SequenceNumber         dd ?
  30.         .AckNumber              dd ?
  31.         .DataOffset             db ?    ; DataOffset[0-3 bits] and Reserved[4-7]
  32.         .Flags                  db ?    ; Reserved[0-1 bits]|URG|ACK|PSH|RST|SYN|FIN
  33.         .Window                 dw ?
  34.         .Checksum               dw ?
  35.         .UrgentPointer          dw ?
  36. ;        .Options                rb 3
  37. ;        .Padding                db ?
  38.         .Data:
  39. ends
  40.  
  41. struct  tcp_in_queue_entry
  42.         .data_ptr       dd ?
  43.         .data_size      dd ?
  44.         .offset         dd ?
  45.         .size:
  46. ends
  47.  
  48. struct  tcp_out_queue_entry
  49.         .data_ptr       dd ?
  50.         .data_size      dd ?
  51.         .ttl            dd ?
  52.         .retries        dd ?
  53.         .owner          dd ?
  54.         .sendproc       dd ?
  55.         .seq_num        dd ?
  56.         .socket         dd ?
  57.         .size:
  58. ends
  59.  
  60. align 4
  61. uglobal
  62.         TCP_PACKETS_TX          rd  MAX_IP
  63.         TCP_PACKETS_RX          rd  MAX_IP
  64.  
  65.         TCP_IN_QUEUE            rd  (tcp_in_queue_entry.size*TCP_QUEUE_SIZE+queue.data)/4
  66.         TCP_OUT_QUEUE           dd  ?
  67.                                 rd  (tcp_out_queue_entry.size*TCP_QUEUE_SIZE)/4
  68. endg
  69.  
  70. align 4
  71. iglobal
  72. stateHandler:
  73.  
  74.   dd  stateTCB_LISTEN
  75.   dd  stateTCB_SYN_SENT
  76.   dd  stateTCB_SYN_RECEIVED
  77.   dd  stateTCB_ESTABLISHED
  78.   dd  stateTCB_FIN_WAIT_1
  79.   dd  stateTCB_FIN_WAIT_2
  80.   dd  stateTCB_CLOSE_WAIT
  81.   dd  stateTCB_CLOSING
  82.   dd  stateTCB_LAST_ACK
  83.   dd  stateTCB_TIME_WAIT
  84.   dd  stateTCB_CLOSED
  85.  
  86. endg
  87.  
  88.  
  89. ;-----------------------------------------------------------------
  90. ;
  91. ; TCP_init
  92. ;
  93. ;  This function resets all TCP variables
  94. ;
  95. ;  IN:  /
  96. ;  OUT: /
  97. ;
  98. ;-----------------------------------------------------------------
  99. align 4
  100. TCP_init:
  101.  
  102.         xor     eax, eax
  103.         mov     edi, TCP_PACKETS_TX
  104.         mov     ecx, 2*MAX_IP
  105.         rep     stosd
  106.  
  107.         init_queue TCP_IN_QUEUE
  108.  
  109. ; tcp_out_queue is a special type of queue:
  110. ; The first dword is a counter of total packets queued.
  111. ; The remaining bytes are socket 'slots' wich use tcp_out_queue_entry data structure.
  112. ; An empty slot is know by the fact that tcp_out_queue_entry.data_ptr (first dword of the slot) is set to 0
  113. ; There are TCP_OUT_QUEUE_SIZE number of slots
  114.  
  115.         xor     eax, eax
  116.         mov     esi, TCP_OUT_QUEUE
  117.         mov     ecx, TCP_QUEUE_SIZE*tcp_out_queue_entry/4+1
  118.         rep     stosd
  119.  
  120.         ret
  121.  
  122.  
  123. ;-----------------------------------------------------------------
  124. ;
  125. ;  TCP_decrease_socket_ttls
  126. ;
  127. ;  IN:  /
  128. ;  OUT: /
  129. ;
  130. ;-----------------------------------------------------------------
  131. align 4
  132. TCP_decrease_socket_ttls:
  133. ; scan through all the sockets, decrementing active timers
  134.  
  135.         mov     ebx, net_sockets
  136.  
  137.         cmp     [ebx + SOCKET_head.NextPtr], 0
  138.         je      .exit
  139.  
  140.   .next_socket:
  141.         mov     ebx, [ebx + SOCKET_head.NextPtr]
  142.         or      ebx, ebx
  143.         jz      .exit
  144.  
  145.         cmp     [ebx + SOCKET_head.Type], IP_PROTO_TCP
  146.         jne     .next_socket
  147.  
  148. ;        DEBUGF  1, "K :   %x-%x: %x-%x-%x-%u\n", [ebx + SOCKET.PID]:2, [ebx + SOCKET.Number]:2, [ebx + SOCKET.LocalPort]:4, [ebx + SOCKET.RemoteIP], [ebx + SOCKET.RemotePort]:4, [ebx + SOCKET.state]
  149.  
  150.         cmp     [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.timer], 0
  151.         jne     .decrement_tcb
  152.         cmp     [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.wndsizeTimer], 0
  153.         jne     .decrement_wnd
  154.         jmp     .next_socket
  155.  
  156.   .decrement_tcb:
  157. ; decrement it, delete socket if TCB timer = 0 & socket in timewait state
  158.         dec     [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.timer]
  159.         jnz     .next_socket
  160.  
  161.         cmp     [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.state], TCB_TIMED_WAIT
  162.         jne     .next_socket
  163.  
  164.         push    [ebx + SOCKET_head.PrevPtr]
  165.         stdcall net_socket_free, ebx
  166.         pop     ebx
  167.         jmp     .next_socket
  168.  
  169.   .decrement_wnd:
  170.         dec     [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.wndsizeTimer]
  171.         jmp     .next_socket
  172.  
  173.   .exit:
  174.         ret
  175.  
  176.  
  177.  
  178. ;-----------------------------------------------------------------
  179. ;
  180. ; TCP_send_queued:
  181. ;
  182. ;  Decreases 'ttl' of tcp packets queued.
  183. ;  if 'ttl' reaches 0, resend the packet and decrease 'retries'
  184. ;  if 'retries' reaches zero, remove the queued packet
  185. ;
  186. ;  IN:  /
  187. ;  OUT: /
  188. ;
  189. ;-----------------------------------------------------------------
  190. align 4
  191. TCP_send_queued:
  192.  
  193.         cmp     [TCP_OUT_QUEUE], 0
  194.         je      .exit
  195.  
  196.         mov     eax, TCP_QUEUE_SIZE
  197.         mov     ecx, [TCP_OUT_QUEUE]
  198.         mov     esi, TCP_OUT_QUEUE+4
  199.  
  200.   .loop:
  201.         cmp     [esi + tcp_out_queue_entry.data_ptr], 0
  202.         jnz     .found_one
  203.         add     esi, tcp_out_queue_entry.size
  204.         loop    .loop
  205.   .exit:
  206.         ret
  207.  
  208.   .found_one:
  209.         dec     [esi + tcp_out_queue_entry.ttl]
  210.         jz      .send_it
  211.   .find_next:
  212.         add     esi, tcp_out_queue_entry.size
  213.         dec     eax
  214.         jz      .exit
  215.         test    ecx, ecx
  216.         jnz     .loop
  217.         ret
  218.  
  219.   .send_it:
  220.         push    eax ecx esi
  221.  
  222.         mov     ebx, [esi + tcp_out_queue_entry.owner]
  223.         push    [esi + tcp_out_queue_entry.data_size]
  224.         push    [esi + tcp_out_queue_entry.data_ptr]
  225.         DEBUGF 1,"Now sending TCP packet %x, size: %u, owner: %x, sendproc %x\n", [esp], [esp+4], ebx, [esi + tcp_out_queue_entry.sendproc]
  226.         inc     [TCP_PACKETS_TX]
  227.         call    [esi + tcp_out_queue_entry.sendproc]
  228.         add     esp, 8
  229.         pop     esi ecx eax
  230.  
  231.         dec     [esi + tcp_out_queue_entry.retries]
  232.         jz      .remove_it
  233.  
  234.         mov     [esi + tcp_out_queue_entry.ttl], TCP_PACKET_TTL
  235.         jmp     .find_next
  236.  
  237.   .remove_it:
  238.         push    [esi + tcp_out_queue_entry.data_ptr]
  239.         mov     [esi + tcp_out_queue_entry.data_ptr], 0
  240.         call    kernel_free
  241.         jmp     .find_next
  242.  
  243.  
  244.  
  245. ;-----------------------------------------------------------------
  246. ;
  247. ; TCP_handler:
  248. ;
  249. ;  Called by IPv4_handler,
  250. ;  this procedure will inject the tcp data diagrams in the application sockets.
  251. ;
  252. ;  IN:  Pointer to buffer in [esp]
  253. ;       size of buffer in [esp+4]
  254. ;       pointer to device struct in ebx
  255. ;       TCP Packet size in ecx
  256. ;       pointer to TCP Packet in edx
  257. ;       SourceAddres (IPv4) in esi
  258. ;  OUT: /
  259. ;
  260. ;-----------------------------------------------------------------
  261. align 4
  262. TCP_handler :
  263.  
  264.        DEBUGF 1,"TCP_Handler\n"
  265.  
  266. ; TODO: validate checksum
  267.  
  268. ; IP Packet TCP Destination Port = local Port
  269. ; IP Packet SA = Remote IP  OR = 0
  270. ; IP Packet TCP Source Port = remote Port  OR = 0
  271.  
  272.         mov     ebx, net_sockets
  273.  
  274.   .socket_loop:
  275.         mov     ebx, [ebx + SOCKET_head.NextPtr]
  276.         or      ebx, ebx
  277.         jz      .dump
  278.  
  279.         mov     ax, [edx + TCP_Packet.DestinationPort]
  280.         cmp     [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.LocalPort], ax
  281.         jne     .socket_loop
  282.  
  283.         mov     eax, [ebx + SOCKET_head.end + IPv4_SOCKET.RemoteIP]
  284.         cmp     eax, esi
  285.         je      @f
  286.         test    eax, eax
  287.         jne     .socket_loop
  288.        @@:
  289.  
  290.         mov     ax, [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.RemotePort]
  291.         cmp     [edx + TCP_Packet.SourcePort] , ax
  292.         je      .found_socket
  293.         test    ax, ax
  294.         jnz     .socket_loop
  295.   .found_socket:
  296.        DEBUGF 1,"Found valid socket for packet\n"
  297.  
  298.         inc     [TCP_PACKETS_RX]
  299.  
  300.         add     ebx, SOCKET_head.lock
  301.         call    wait_mutex
  302.         sub     ebx, SOCKET_head.lock
  303.  
  304. ;-------------------------------
  305. ; ebx is pointer to socket
  306. ; ecx is size of tcp packet
  307. ; edx is pointer to tcp packet
  308.  
  309. ; calculate header length
  310.         movzx   eax, [edx + TCP_Packet.DataOffset]
  311.         and     eax, 11110000b
  312.         shr     eax, 2
  313.        DEBUGF 1,"TCP header size: %u\n", eax
  314.         sub     ecx, eax
  315.  
  316. ;-------------------------------
  317. ; ecx is size of tcp data
  318.  
  319. ; as a Packet has been received, update the TCB timer
  320.         mov     [ebx +  SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.timer], TCP_SOCKET_TTL
  321.  
  322. ; If the received Packet has an ACK bit set, remove any Packets in the resend queue that this received Packet acknowledges
  323.         test    [edx + TCP_Packet.Flags], TH_ACK
  324.         jz      .no_ack                                  ; No ACK, so no data yet
  325.  
  326. ; Calculate ACK number
  327.         mov     edi, [edx + TCP_Packet.AckNumber]
  328.         bswap   edi
  329.         mov     [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.last_ack_number], edi
  330.        DEBUGF 1,"Setting last_ack_number to %u\n", edi
  331.         bswap   edi
  332.  
  333. ; Dequeue all acknowledged packets
  334.         cmp     [TCP_OUT_QUEUE], 0              ; first, check if any packets are queued at all
  335.         je      .no_ack
  336.  
  337.         push    ecx
  338.        DEBUGF 1,"Removing all queued packets with smaller ACK\n"
  339.         mov     ecx, TCP_QUEUE_SIZE
  340.         mov     esi, TCP_OUT_QUEUE+4
  341.   .loop:
  342.         cmp     [esi + tcp_out_queue_entry.data_ptr], 0
  343.         je      .maybe_next
  344.  
  345.         cmp     [esi + tcp_out_queue_entry.socket], ebx
  346.         jne     .maybe_next
  347.  
  348.         cmp     [esi + tcp_out_queue_entry.seq_num], edi
  349.         jg      .maybe_next
  350.  
  351.        DEBUGF 1,"Removing a queued packet\n"
  352.  
  353.         push    [esi + tcp_out_queue_entry.data_ptr]
  354.         mov     [esi + tcp_out_queue_entry.data_ptr], 0
  355.         dec     [TCP_OUT_QUEUE]
  356.         call    kernel_free
  357.  
  358.   .maybe_next:
  359.         add     esi, tcp_out_queue_entry.size
  360.         loop    .loop
  361.         pop     ecx
  362.  
  363.  
  364. ; Now call the correct handler, depending on the socket state
  365.   .no_ack:
  366.         mov     eax, [ebx +  SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.state]
  367.  
  368.         cmp     eax, TCB_LISTEN
  369.         jb      .dump
  370.         cmp     eax, TCB_CLOSED
  371.         ja      .dump
  372.  
  373.         dec     eax
  374.         shl     eax, 2
  375.         add     eax, stateHandler
  376.  
  377.         call    dword[eax]
  378.  
  379.   .dump:
  380.         DEBUGF 1,"Dumping TCP packet\n"
  381.         call    kernel_free
  382.         add     esp, 4 ; pop (balance stack)
  383.  
  384.         ret
  385.  
  386.  
  387.  
  388. ;-----------------------------------------------------------------
  389. ;
  390. ; TCP_send  (Assumes socket mutex set)
  391. ;
  392. ; IN: eax = socket pointer
  393. ;      bl = flags
  394. ;      ecx = number of bytes to send, may be set to 0
  395. ;      esi = pointer to data
  396. ;
  397. ;-----------------------------------------------------------------
  398. align 4
  399. TCP_send:
  400.  
  401.         DEBUGF 1,"Creating TCP packet, socket: %x, flags: %x\n",eax, bl
  402.  
  403.         mov     di , IP_PROTO_TCP
  404.         add     ecx, TCP_Packet.Data
  405.  
  406.         push    bx eax esi
  407. ; Create an IPv4 Packet of the correct size
  408.         mov     ebx, [eax + SOCKET_head.end + IPv4_SOCKET.LocalIP]
  409.         mov     eax, [eax + SOCKET_head.end + IPv4_SOCKET.RemoteIP]
  410.  
  411.         call    IPv4_create_packet
  412.         cmp     edi, -1
  413.         je      .fail
  414.  
  415. ; If there is any data, copy it first
  416.         pop     esi
  417.         push    edi
  418.         add     edi, TCP_Packet.Data
  419.         sub     ecx, TCP_Packet.Data
  420.  
  421.         shr     ecx, 1
  422.         jnc     .nb
  423.         movsb
  424. .nb:    shr     ecx, 1
  425.         jnc     .nw
  426.         movsw
  427. .nw:    test    ecx, ecx
  428.         jz      .nd
  429.         rep     movsd
  430. .nd:
  431.         pop     edi
  432.  
  433. ; Fill in the TCP header
  434.         pop     esi
  435.  
  436. ; fill in tcp sequence number
  437.         push    [esi + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.SND_NXT]
  438.         pop     [edi + TCP_Packet.SequenceNumber]
  439.         inc_INET (ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.SND_NXT) ;;;;;;;;
  440.  
  441. ; Fill in local and remote ports
  442.         push    dword [esi + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.LocalPort]
  443.         pop     dword [edi + TCP_Packet.SourcePort]
  444.  
  445. ; Acknumber
  446.         push    [esi + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.RCV_NXT]
  447.         pop     [edi + TCP_Packet.AckNumber]
  448.  
  449. ; Fill  in other tcp options
  450.         pop     cx
  451.         mov     [edi + TCP_Packet.Flags], cl
  452.         mov     [edi + TCP_Packet.Window], 0x0005          ; 1280 bytes
  453.         mov     [edi + TCP_Packet.UrgentPointer], 0
  454.         mov     [edi + TCP_Packet.DataOffset], 0x50
  455.         mov     [edi + TCP_Packet.Checksum], 0
  456.  
  457. ; Push pointer to and size of total packet (needed for send procedure)
  458.         push    edx eax
  459.  
  460. ; push socket number (for TCP_add_to_queue)
  461.         push    esi
  462.  
  463. ; Now, calculate the checksum                  ; TODO: calculate correct checksum for packets with data
  464.         pushw   TCP_Packet.Data shl 8
  465.         pushw   IP_PROTO_TCP shl 8
  466.         pushd   [edi-4] ; destination address  ; TODO: fix this, IPv4 packet could have options..
  467.         pushd   [edi-8] ; source address
  468.  
  469.         xor     edx, edx
  470.         mov     ecx, TCP_Packet.Data
  471.         mov     esi, edi
  472.         call    checksum_1
  473.         mov     ecx, 12
  474.         mov     esi, esp
  475.         call    checksum_1
  476.         add     esp, 12                                    ; remove the pseudoheader from stack
  477. ; and store it in TCP header
  478.         call    checksum_2
  479.         mov     [edi + TCP_Packet.Checksum], dx
  480.  
  481. ; At last send the packet!
  482.         DEBUGF 1,"Sending TCP Packet to device %x\n", ebx
  483.         mov     edx, [edi + TCP_Packet.SequenceNumber]
  484.         bswap   edx
  485.         mov     esi, [ebx + ETH_DEVICE.transmit]
  486.         pop     edi
  487.         jmp     TCP_queue
  488.  
  489.   .fail:
  490.         add     esp, 2+4
  491.         or      eax, -1
  492.         ret
  493.  
  494.  
  495. ;-----------------------------------------------------------------
  496. ;
  497. ;  Queue a TCP packet for sending
  498. ;
  499. ;  IN:  [esp] pointer to buffer
  500. ;       [esp + 4] size of buffer
  501. ;       ebx = driver struct
  502. ;       esi = sender proc
  503. ;       edx = sequence number of this packet in normal byte order
  504. ;       edi = socket number
  505. ;  OUT: /
  506. ;
  507. ;-----------------------------------------------------------------
  508. align 4
  509. TCP_queue:
  510.  
  511.         bswap   edx
  512.         DEBUGF 1,"Adding packet to TCP queue, buffer: %x, size: %u, driver: %x, acknum: %u\n", [esp], [esp+4], ebx, edx
  513.         bswap   edx
  514.  
  515.         cmp     [TCP_OUT_QUEUE], TCP_QUEUE_SIZE
  516.         jge     .full
  517.  
  518.         mov     ecx, TCP_QUEUE_SIZE
  519.         mov     eax, TCP_OUT_QUEUE+4
  520.  
  521.   .loop:
  522.         cmp     [eax + tcp_out_queue_entry.data_ptr], 0
  523.         je      .found_it
  524.         add     eax, tcp_out_queue_entry.size
  525.         loop    .loop
  526.  
  527.   .full:                        ; silently discard the packet
  528.         DEBUGF 1,"TCP queue is full!\n"
  529.  
  530.         call    kernel_free
  531.         add     esp, 4
  532.  
  533.         ret
  534.  
  535.   .found_it:                    ; eax points to empty queue entry
  536.  
  537.         pop     [eax + tcp_out_queue_entry.data_ptr]
  538.         pop     [eax + tcp_out_queue_entry.data_size]
  539.         mov     [eax + tcp_out_queue_entry.ttl], 1                      ; send immediately
  540.         mov     [eax + tcp_out_queue_entry.retries], TCP_RETRIES
  541.         mov     [eax + tcp_out_queue_entry.owner], ebx
  542.         mov     [eax + tcp_out_queue_entry.sendproc], esi
  543.         mov     [eax + tcp_out_queue_entry.seq_num], edx
  544.         mov     [eax + tcp_out_queue_entry.socket], edi
  545.  
  546.         inc     [TCP_OUT_QUEUE]
  547.  
  548.         sub     eax, TCP_OUT_QUEUE+4
  549.         DEBUGF 1,"Added to queue in pos %u\n", eax
  550.  
  551.         ret
  552.  
  553.  
  554.  
  555.  
  556.  
  557. ;---------- TCB state handlers start here
  558.  
  559.  
  560.  
  561.  
  562. align 4
  563. stateTCB_LISTEN:
  564.  
  565.         DEBUGF  1,"TCBStateHandler: Listen\n"
  566.  
  567.         test    [edx + TCP_Packet.Flags], TH_SYN        ; SYN packet? => send syn+ack, open new socket and set connection to established
  568.         jz      .exit
  569. ; Exit if backlog queue is full
  570.         mov     ax, [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.backlog_cur]
  571.         cmp     ax, [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.backlog]
  572.         jae     .exit
  573. ; Allocate new socket
  574.         push    esi edi
  575.         call    net_socket_alloc
  576.         test    eax, eax
  577.         jz      .fail
  578. ; Copy structure from current socket to new, including lock
  579.         lea     esi, [ebx + SOCKET_head.PID]            ; yes, PID must also be copied
  580.         lea     edi, [eax + SOCKET_head.PID]
  581.         mov     ecx, ((SOCKET_head.end - SOCKET_head.PID) + IPv4_SOCKET.end + TCP_SOCKET.end + 3)/4
  582.         rep     movsd
  583.         pop     edi esi
  584. ; Push pointer to new socket to queue
  585.         movzx   ecx, [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.backlog_cur]
  586.         inc     [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.backlog_cur]
  587.         mov     [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.end + ecx*4], eax
  588.  
  589.         mov     [eax + SOCKET_head.end + IPv4_SOCKET.RemoteIP], esi ; IP source address
  590.         mov     cx, [edx + TCP_Packet.SourcePort]
  591.         mov     [eax + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.RemotePort], cx
  592.         mov     ecx, [edx + TCP_Packet.SequenceNumber]
  593.         mov     [eax + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.IRS], ecx
  594.         mov     [eax + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.RCV_NXT], ecx
  595.         lea     esi, [eax + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.RCV_NXT]
  596.         inc_INET esi ; RCV.NXT
  597.         mov     ecx, [eax + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.ISS]
  598.         mov     [eax + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.SND_NXT], ecx
  599.  
  600.         mov     [ebx + SOCKET_head.lock], 0
  601.  
  602.         push    eax
  603. ; Now construct the response
  604.         mov     bl, TH_SYN + TH_ACK
  605.         xor     ecx, ecx
  606.         call    TCP_send
  607.         pop     eax
  608.  
  609.         mov     [eax + SOCKET_head.lock], 0
  610.         mov     [eax +  SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.state], TCB_SYN_RECEIVED
  611.         call    notify_network_event
  612.         ret
  613.  
  614.   .exit:
  615.         mov     [ebx + SOCKET_head.lock], 0
  616.         ret
  617.  
  618.   .fail:
  619.         add     esp, 8
  620.         mov     [ebx + SOCKET_head.lock], 0
  621.         ret
  622.  
  623.  
  624. align 4
  625. stateTCB_SYN_SENT:
  626.  
  627.         DEBUGF  1,"TCBStateHandler: Syn_Sent\n"
  628.  
  629.         ; We are awaiting an ACK to our SYN, with a SYM
  630.         ; Look at control flags - expecting an ACK
  631.  
  632.         mov     al, [edx + TCP_Packet.Flags]
  633.  
  634.         test    al, TH_RST
  635.         jnz     .reset                  ; jump if RST bit set
  636.  
  637.         push    [edx + TCP_Packet.SequenceNumber]                                    ;;
  638.         pop     [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.RCV_NXT]       ;;
  639.         inc_INET (ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.RCV_NXT)      ;;
  640.  
  641.  
  642.         push    [edx + TCP_Packet.AckNumber]                                        ;;;;;;
  643.         pop     [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.SND_NXT]      ;;;;;;
  644.  
  645.         and     al, TH_SYN + TH_ACK
  646.         jz      .exit                   ; jump if none of the following is set: RST, SYN, ACK
  647.  
  648.         test    al, TH_ACK
  649.         jz     .onlysyn                 ; jump if only SYN bit is set
  650.  
  651.         ; If we arrived here, SYN and ACK are set
  652.  
  653.         mov     [ebx +  SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.state], TCB_ESTABLISHED
  654.         pushw   TH_ACK
  655.  
  656.   .send:        ; Send an ACK
  657.         mov     eax, ebx
  658.         pop     bx
  659.         push    eax
  660.         xor     ecx, ecx
  661.         call    TCP_send
  662.         pop     ebx
  663.  
  664.   .exit:
  665.         mov     [ebx + SOCKET_head.lock], 0
  666.         ret
  667.  
  668.   .reset:
  669.         ; TODO: ....
  670.  
  671.         ; remove all queued TCP packets for this connection !
  672.  
  673.         mov     [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.state], TCB_CLOSED
  674.         mov     [ebx + SOCKET_head.lock], 0
  675.         ret
  676.  
  677.   .onlysyn:
  678.         mov     [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.state], TCB_SYN_RECEIVED
  679.         pushw   TH_SYN + TH_ACK
  680.         jmp     .send
  681.  
  682.  
  683.  
  684. align 4
  685. stateTCB_SYN_RECEIVED:
  686.  
  687.         DEBUGF  1,"TCBStateHandler: Syn_received\n"
  688.  
  689.         test    [edx + TCP_Packet.Flags], TH_RST        ; reset connection? => LISTEN
  690.         jz      .check_ack
  691.  
  692.         push    [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.OrigRemotePort]
  693.         pop     [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.RemotePort]
  694.         push    [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.OrigRemoteIP]
  695.         pop     [ebx + SOCKET_head.end + IPv4_SOCKET.RemoteIP]
  696.  
  697.         mov     [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.state], TCB_LISTEN
  698.         jmp     .exit
  699.  
  700.   .check_ack:
  701.         test    [edx + TCP_Packet.Flags], TH_ACK        ; ACK? => connection established!
  702.         jz      .exit
  703.  
  704.         mov     [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.state], TCB_ESTABLISHED
  705.         mov     eax, ebx
  706.         call    notify_network_event
  707.  
  708.   .exit:
  709.         mov     [ebx + SOCKET_head.lock], 0
  710.         ret
  711.  
  712.  
  713.  
  714. align 4
  715. stateTCB_ESTABLISHED:
  716.  
  717.         DEBUGF  1,"TCBStateHandler: Established\n"
  718.  
  719.         mov     eax, [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.RCV_NXT]
  720.         bswap   eax
  721.         DEBUGF  1,"RCV_NXT is set to:%u\n", eax
  722.         bswap   eax
  723.         cmp     eax, [edx + TCP_Packet.SequenceNumber]
  724.         jne     .exit
  725.  
  726. ; Calculate next sequencenumber
  727.         test    ecx, ecx
  728.         jnz     @f
  729.         inc     ecx
  730.        @@:
  731.         add_INET (ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.RCV_NXT)
  732.  
  733.         test    [edx + TCP_Packet.Flags], TH_FIN
  734.         jnz     .fin
  735.  
  736.   .check_ack:
  737.         test    [edx + TCP_Packet.Flags], TH_ACK
  738.         jz      .exit
  739.  
  740.         DEBUGF  1,"Received ACK\n"
  741. ; First, look at the incoming window. If this is less than or equal to 1024,
  742. ; Set the socket window timer to 1. This will stop an additional Packets being queued.
  743. ; ** I may need to tweak this value, since I do not know how many Packets are already queued
  744.         push    ecx
  745.         mov     cx, [edx + TCP_Packet.Window]
  746.         xchg    cl, ch
  747.         cmp     cx, 1024
  748.         ja      @f
  749.         mov     [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.wndsizeTimer], 1
  750.       @@:
  751.         pop     ecx
  752.  
  753. ; Now, see if we received any data
  754.         test    ecx, ecx
  755.         jz      .ack
  756.  
  757.         DEBUGF  1,"Got %u bytes data!\n", ecx
  758. ; calculate header length
  759.         movzx   eax, [edx + TCP_Packet.DataOffset]
  760.         and     eax, 11110000b
  761.         shr     eax, 2
  762.        DEBUGF 1,"TCP header size: %u\n", eax
  763.         add     edx, eax
  764.         add     esp, 4
  765.         pop     esi
  766.         add     esp, 4
  767.         sub     edx, esi
  768.         mov     edi, edx
  769.         mov     eax, ebx
  770.         jmp     socket_internal_receiver        ; Place the data from packet into socket
  771.  
  772.   .ack:
  773.         mov     eax, ebx
  774.         mov     bl, TH_ACK
  775.         push    eax
  776.         xor     ecx, ecx
  777.         call    TCP_send                    ; send the ack
  778.         pop     ebx
  779.   .exit:
  780.         mov     [ebx + SOCKET_head.lock], 0
  781.         ret
  782.  
  783.   .fin:
  784. ; Remove all resend entries from the queue
  785.         mov     ecx, TCP_QUEUE_SIZE
  786.         mov     esi, TCP_OUT_QUEUE+4
  787.  
  788.   .removeloop:
  789.         cmp     [esi + tcp_out_queue_entry.data_ptr], 0
  790.         je      .maybe_next
  791.  
  792.         ; TODO: check if the packets belong to the same tcp connection !
  793.  
  794.        DEBUGF 1,"Removing a queued packet\n"
  795.  
  796.         push    [esi + tcp_out_queue_entry.data_ptr]
  797.         mov     [esi + tcp_out_queue_entry.data_ptr], 0
  798.         dec     [TCP_OUT_QUEUE]
  799.         call    kernel_free
  800.  
  801.   .maybe_next:
  802.         add     esi, tcp_out_queue_entry.size
  803.         loop    .removeloop
  804.  
  805. ; Send an ACK to that fin, and enter closewait state
  806.         mov     [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.state], TCB_CLOSE_WAIT
  807.         jmp     .check_ack
  808.  
  809.  
  810.  
  811. align 4
  812. stateTCB_FIN_WAIT_1:
  813.  
  814.         DEBUGF  1,"TCBStateHandler: Fin_wait_1\n"
  815.  
  816.         ; We can either receive an ACK of a fin, or a fin
  817.         mov     al, [edx + TCP_Packet.Flags]
  818.         and     al, TH_FIN + TH_ACK
  819.  
  820.         cmp     al, TH_ACK
  821.         jne     @f
  822.  
  823.         ; It was an ACK
  824.         mov     [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.state], TCB_FIN_WAIT_2
  825.         jmp     .exit
  826.  
  827.     @@: mov     [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.state], TCB_CLOSING
  828.         cmp     al, TH_FIN
  829.         je      @f
  830.         mov     [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.state], TCB_TIMED_WAIT
  831.  
  832.     @@:
  833.  
  834. ;        lea     esi, [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.RCV_NXT]
  835. ;        inc_INET esi
  836.  
  837.         ; Send an ACK
  838.         mov     eax, ebx
  839.         mov     bl, TH_ACK
  840.         push    eax
  841.         xor     ecx, ecx
  842.         call    TCP_send
  843.         pop     ebx
  844.  
  845.   .exit:
  846.         mov     [ebx + SOCKET_head.lock], 0
  847.         ret
  848.  
  849.  
  850.  
  851. align 4
  852. stateTCB_FIN_WAIT_2:
  853.  
  854.         DEBUGF  1,"TCBStateHandler: Fin_wait_2\n"
  855.  
  856.         test    [edx + TCP_Packet.Flags], TH_FIN
  857.         jz      .exit
  858.  
  859.         ; Change state, as we have a fin
  860.         mov     [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.state], TCB_TIMED_WAIT
  861.  
  862.         lea     esi, [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.RCV_NXT]
  863.         inc_INET esi
  864.  
  865.         mov     [ebx + SOCKET_head.lock], 0
  866.  
  867.         ; Send an ACK
  868.         mov     eax, ebx
  869.         mov     bl, TH_ACK
  870.         push    eax
  871.         xor     ecx, ecx
  872.         call    TCP_send
  873.         pop     ebx
  874.  
  875.   .exit:
  876.         mov     [ebx + SOCKET_head.lock], 0
  877.         ret
  878.  
  879.  
  880.  
  881. align 4
  882. stateTCB_CLOSE_WAIT:
  883.  
  884.         DEBUGF  1,"TCBStateHandler: close_wait\n"
  885.         ; Intentionally left empty
  886.         ; socket_close_tcp handles this
  887.  
  888.         mov     [ebx + SOCKET_head.lock], 0
  889.         ret
  890.  
  891.  
  892.  
  893. align 4
  894. stateTCB_CLOSING:
  895.  
  896.         DEBUGF  1,"TCBStateHandler: closingn\n"
  897.  
  898.         ; We can either receive an ACK of a fin, or a fin
  899.         test    [edx + TCP_Packet.Flags], TH_ACK
  900.         jz      .exit
  901.  
  902.         mov     [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.state], TCB_TIMED_WAIT
  903.  
  904.   .exit:
  905.  
  906.         mov     [ebx + SOCKET_head.lock], 0
  907.         ret
  908.  
  909.  
  910. align 4
  911. stateTCB_LAST_ACK:
  912.  
  913.         DEBUGF  1,"TCBStateHandler: last_ackn\n"
  914.  
  915.         ; Look at control flags - expecting an ACK
  916.         test    [edx + TCP_Packet.Flags], TH_ACK
  917.         jz      .exit
  918.  
  919.         mov     [ebx + SOCKET_head.lock], 0
  920.  
  921.         ; delete the socket
  922.         stdcall net_socket_free, ebx
  923.  
  924.   .exit:
  925.         ret
  926.  
  927.  
  928. align 4
  929. stateTCB_TIME_WAIT:
  930.  
  931.         DEBUGF  1,"TCBStateHandler: time_wait\n"
  932.  
  933.         mov     [ebx + SOCKET_head.lock], 0
  934.  
  935.         ret
  936.  
  937.  
  938. align 4
  939. stateTCB_CLOSED:
  940.  
  941.         DEBUGF  1,"TCBStateHandler: closed\n"
  942.  
  943.         mov     [ebx + SOCKET_head.lock], 0
  944.  
  945.         ret
  946.  
  947.  
  948.  
  949. ;---------------------------------------------------------------------------
  950. ;
  951. ; TCP_API
  952. ;
  953. ; This function is called by system function 75
  954. ;
  955. ; IN:  subfunction number in bl
  956. ;      device number in bh
  957. ;      ecx, edx, .. depends on subfunction
  958. ;
  959. ; OUT:
  960. ;
  961. ;---------------------------------------------------------------------------
  962. align 4
  963. TCP_API:
  964.  
  965.         movzx   eax, bh
  966.         shl     eax, 2
  967.  
  968.         test    bl, bl
  969.         jz      .packets_tx     ; 0
  970.         dec     bl
  971.         jz      .packets_rx     ; 1
  972.  
  973. .error:
  974.         mov     eax, -1
  975.         ret
  976.  
  977. .packets_tx:
  978.         add     eax, TCP_PACKETS_TX
  979.         mov     eax, [eax]
  980.         ret
  981.  
  982. .packets_rx:
  983.         add     eax, TCP_PACKETS_RX
  984.         mov     eax, [eax]
  985.         ret
  986.