Subversion Repositories Kolibri OS

Rev

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

  1. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  2. ;;                                                                 ;;
  3. ;;  TCP.INC                                                        ;;
  4. ;;                                                                 ;;
  5. ;;  TCP Processes for Menuet OS  TCP/IP stack                      ;;
  6. ;;                                                                 ;;
  7. ;;  Version 0.6  4th July 2004                                       ;;
  8. ;;                                                                 ;;
  9. ;;  Copyright 2002 Mike Hibbett, mikeh@oceanfree.net               ;;
  10. ;;                                                                 ;;
  11. ;;  See file COPYING for details                                   ;;
  12. ;;  v0.6 : Added reset handling in the established state           ;;
  13. ;;         Added a timer per socket to allow delays when rx window ;;
  14. ;;         gets below 1KB                                          ;;
  15. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  16.  
  17.  
  18. ;*******************************************************************
  19. ;   Interface
  20. ;
  21. ;       tcp_tx_handler      Handles the TCP transmit queue
  22. ;       tcp_rx              The protocol handler for received data
  23. ;       buildTCPPacket      fills in the packet headers and data
  24. ;       tcpStateMachine     Main state machine for received TCP packets
  25. ;       tcp_tcb_handler     1s timer, to erase tcb's in TIME_WAIT state
  26. ;
  27. ;*******************************************************************
  28.  
  29.  
  30.  
  31. ;***************************************************************************
  32. ;   Function
  33. ;      tcp_tcb_handler
  34. ;
  35. ;   Description
  36. ;       Handles sockets in the timewait state, closing them
  37. ;       when the TCB timer expires
  38. ;
  39. ;***************************************************************************
  40. tcp_tcb_handler:
  41.     ; scan through all the sockets, decrementing active timers
  42.  
  43.     mov     eax, SOCKETBUFFSIZE * NUM_SOCKETS
  44.     mov     ecx, NUM_SOCKETS
  45.  
  46. tth1:
  47.     sub     eax, SOCKETBUFFSIZE
  48.     cmp     [eax + sockets + 32], dword 0
  49.     jne     tth2
  50.  
  51. tth1a:
  52.     cmp     [eax + sockets + 72], dword 0
  53.     jne     tth4
  54.  
  55.     loop    tth1
  56.     ret
  57.  
  58. tth2:
  59.     ; decrement it, delete socket if TCB timer = 0 & socket in timewait state
  60.     pusha
  61.     dec     dword [eax + sockets + 32]
  62.     cmp     [eax + sockets + 32], dword 0
  63.     jne     tth3
  64.  
  65.     cmp     [eax + sockets + 28], dword TCB_TIME_WAIT
  66.     jne     tth3
  67.  
  68.     ; OK, delete socket
  69.     mov     edi, eax
  70.     add     edi, sockets
  71.  
  72.     xor     eax, eax
  73.     mov     ecx, SOCKETHEADERSIZE
  74.     cld
  75.     rep     stosb
  76.  
  77. tth3:
  78.     popa
  79.  
  80.     jmp     tth1a
  81.  
  82.     loop    tth1
  83.     ret
  84.  
  85.     ; TODO - prove it works!
  86. tth4:
  87.     dec     dword [eax + sockets + 72]
  88.     loop    tth1
  89.     ret
  90.  
  91.  
  92.  
  93.  
  94. tth_exit:
  95.     ret
  96.  
  97.  
  98. ;***************************************************************************
  99. ;   Function
  100. ;      tcp_tx_handler
  101. ;
  102. ;   Description
  103. ;       Handles queued TCP data
  104. ;       This is a kernel function, called by stack_handler
  105. ;
  106. ;***************************************************************************
  107. tcp_tx_handler:
  108.     ; decrement all resend buffers timers. If they
  109.     ; expire, queue them for sending, and restart the timer.
  110.     ; If the retries counter reach 0, delete the entry
  111.  
  112.     mov     esi, resendQ
  113.     mov     ecx, 0
  114.  
  115. tth001:
  116.     cmp     ecx, NUMRESENDENTRIES
  117.     je      tth003              ; None left
  118.     cmp     [esi], byte 0xFF
  119.     jne      tth002             ; found one
  120.     inc     ecx
  121.     add     esi, 4
  122.     jmp     tth001
  123.  
  124. tth002:
  125.     ; we have one. decrement it's timer by 1
  126.     dec     word [esi+2]
  127.     mov     ax, [esi+2]
  128.     cmp     ax, 0
  129.     je     tth002a
  130.     inc     ecx
  131.     add     esi, 4
  132.     jmp     tth001              ; Timer not zero, so move on
  133.  
  134. tth002a:
  135.     mov     bl, 0xff
  136.     ; restart timer, and decrement retries
  137.     ; After the first resend, back of on next, by a factor of 5
  138.     mov     [esi+2], word TCP_TIMEOUT * 5
  139.     dec     byte [esi+1]
  140.     mov     al, [esi+1]
  141.     cmp     al, 0
  142.     jne     tth004
  143.  
  144.     ; retries now 0, so delete from queue
  145.     xchg     [esi], bl
  146. tth004:
  147.  
  148.     ; resend packet
  149.     pusha
  150.  
  151.     mov     eax, EMPTY_QUEUE
  152.     call    dequeue
  153.     cmp     ax, NO_BUFFER
  154.     jne      tth004z
  155.  
  156.     ; TODO - try again in 10ms.
  157.     cmp     bl, 0xff
  158.     jne     tth004za
  159.     mov     [esi], bl
  160.  
  161. tth004za:
  162.     ; Mark it to expire in 10ms - 1 tick
  163.     mov     [esi+1], byte 1
  164.     mov     [esi+2], word 1
  165.     jmp     tth005
  166.  
  167. tth004z:
  168.     ; we have a buffer # in ax
  169.  
  170.     push    eax
  171.     push    ecx
  172.     mov     ecx, IPBUFFSIZE
  173.     mul     ecx
  174.     add     eax, IPbuffs
  175.  
  176.     ; we have the buffer address in eax
  177.     mov     edi, eax
  178.     pop     ecx
  179.     ; get resend data address
  180.     inc     ecx
  181.     ; Now get buffer location, and copy buffer across. argh! more copying,,
  182.     mov     esi, resendBuffer - IPBUFFSIZE
  183. tth004a:
  184.     add     esi, IPBUFFSIZE
  185.     loop    tth004a
  186.  
  187.     ; we have resend buffer location in esi
  188.     mov     ecx, IPBUFFSIZE
  189.  
  190.     ; copy data across
  191.     cld
  192.     rep     movsb
  193.  
  194.     ; queue packet
  195.  
  196.  
  197.  
  198.     mov     eax, NET1OUT_QUEUE
  199.  
  200.     mov     edx, [stack_ip]
  201.     mov     ecx, [ edi + 16 ]
  202.     cmp     edx, ecx
  203.     jne     tth004b
  204.     mov     eax, IPIN_QUEUE
  205.  
  206. tth004b:
  207.     pop     ebx
  208.  
  209.     call    queue
  210.  
  211.  
  212. tth005:
  213.     popa
  214.  
  215.     inc     ecx
  216.     add     esi, 4
  217.     jmp     tth001
  218.  
  219. tth003:
  220.     ret
  221.  
  222.  
  223.  
  224.  
  225. ;***************************************************************************
  226. ;   Function
  227. ;      tcp_rx
  228. ;
  229. ;   Description
  230. ;       TCP protocol handler
  231. ;       This is a kernel function, called by ip_rx
  232. ;       IP buffer address given in edx
  233. ;          IP buffer number in eax
  234. ;          Free up (or re-use) IP buffer when finished
  235. ;
  236. ;***************************************************************************
  237. tcp_rx:
  238.     ; The process is as follows.
  239.     ; Look for a socket with matching remote IP, remote port, local port
  240.     ; if not found, then
  241.     ; look for remote IP + local port match ( where sockets remote port = 0)
  242.     ; if not found, then
  243.     ; look for a socket where local socket port == IP packets remote port
  244.     ; where sockets remote port, remote IP = 0
  245.     ; discard if not found
  246.     ; Call sockets tcbStateMachine, with pointer to packet.
  247.     ; the state machine will not delete the packet, so do that here.
  248.  
  249.     push        eax
  250.  
  251.     ; Look for a socket where
  252.     ; IP Packet TCP Destination Port = local Port
  253.     ; IP Packet SA = Remote IP
  254.     ; IP Packet TCP Source Port = remote Port
  255.  
  256.     mov     eax, SOCKETBUFFSIZE * NUM_SOCKETS
  257.     mov     ecx, NUM_SOCKETS
  258. ss1:
  259.     sub     eax, SOCKETBUFFSIZE
  260.     movzx   ebx, word [edx + 22]     ; get the dest. port from the TCP hdr
  261.     cmp     [eax + sockets + 12], bx ; compare with socket's local port
  262.     jnz     nxttst1                        ; different - try next socket
  263.  
  264.     movzx   ebx, word [edx + 20]       ; get the source port from the TCP hdr
  265.     cmp     [eax + sockets + 20], bx ; compare with socket's remote port
  266.     jnz     nxttst1                        ; different - try next socket
  267.  
  268.  
  269.     mov     ebx, [edx + 12]           ; get the source IP Addr from the IP hdr
  270.     cmp     [eax + sockets + 16], ebx ; compare with socket's remote IP
  271.     jnz     nxttst1                        ; different - try next socket
  272.  
  273.     ; We have a complete match - use this socket
  274.     jmp     tcprx_001
  275.  
  276. nxttst1:
  277.     loop    ss1                     ; Return back if no match
  278.  
  279.     ; If we got here, there was no match
  280.     ; Look for a socket where
  281.     ; IP Packet TCP Destination Port = local Port
  282.     ; IP Packet SA = Remote IP
  283.     ; socket remote Port = 0
  284.  
  285.     mov     eax, SOCKETBUFFSIZE * NUM_SOCKETS
  286.     mov     ecx, NUM_SOCKETS
  287.  
  288. ss2:
  289.     sub     eax, SOCKETBUFFSIZE
  290.  
  291.     movzx   ebx, word [edx + 22]     ; get the dest. port from the TCP hdr
  292.     cmp     [eax + sockets + 12], bx ; compare with socket's local port
  293.     jnz     nxttst2                        ; different - try next socket
  294.  
  295.     mov     ebx, [edx + 12]          ; get the source IP Addr from the IP hdr
  296.     cmp     [eax + sockets + 16], ebx ; compare with socket's remote IP
  297.     jnz     nxttst2                        ; different - try next socket
  298.  
  299.     mov     ebx, 0
  300.     cmp     [eax + sockets + 20], bx ; only match a remote socket of 0
  301.     jnz     nxttst2                        ; different - try next socket
  302.  
  303.     ; We have a complete match - use this socket
  304.     jmp     tcprx_001
  305.  
  306. nxttst2:
  307.     loop    ss2                     ; Return back if no match
  308.  
  309.     ; If we got here, there was no match
  310.     ; Look for a socket where
  311.     ; IP Packet TCP Destination Port = local Port
  312.     ; socket Remote IP = 0
  313.     ; socket remote Port = 0
  314.  
  315.     mov     eax, SOCKETBUFFSIZE * NUM_SOCKETS
  316.     mov     ecx, NUM_SOCKETS
  317.  
  318. ss3:
  319.     sub     eax, SOCKETBUFFSIZE
  320.  
  321.     movzx   ebx, word [edx + 22]     ; get destination port from the TCP hdr
  322.     cmp     [eax + sockets + 12], bx ; compare with socket's local port
  323.     jnz     nxttst3                        ; different - try next socket
  324.  
  325.     mov     ebx, 0
  326.     cmp     [eax + sockets + 20], bx ; only match a remote socket of 0
  327.     jnz     nxttst3                        ; different - try next socket
  328.  
  329.     mov     ebx, 0
  330.     cmp     [eax + sockets + 16], ebx ; only match a socket remote IP of 0
  331.     jnz     nxttst3                        ; different - try next socket
  332.  
  333.     ; We have a complete match - use this socket
  334.     jmp     tcprx_001
  335.  
  336. nxttst3:
  337.     loop    ss3                     ; Return back if no match
  338.  
  339.     ; If we got here, we need to reject the packet
  340.     inc     dword [dumped_rx_count]
  341.     jmp     tcprx_exit
  342.  
  343. tcprx_001:
  344.     ; We have a valid socket/TCB, so call the TCB State Machine for that skt.
  345.     ; socket is pointed to by [eax + sockets]
  346.     ; IP packet is pointed to by [edx]
  347.     ; IP buffer number is on stack ( it will be popped at the end)
  348.     call    tcpStateMachine
  349.  
  350. tcprx_exit:
  351.     pop     eax
  352.     call    freeBuff
  353.  
  354.     ret
  355.  
  356.  
  357.  
  358. ;***************************************************************************
  359. ;   Function
  360. ;      buildTCPPacket
  361. ;
  362. ;   Description
  363. ;       builds an IP Packet with TCP data fully populated for transmission
  364. ;       You may destroy any and all registers
  365. ;          TCP control flags specified in bl
  366. ;          This TCB is in [sktAddr]
  367. ;          User data pointed to by esi
  368. ;       Data length in ecx
  369. ;          Transmit buffer number in eax
  370. ;
  371. ;***************************************************************************
  372. buildTCPPacket:
  373.     push    ecx                        ; Save data length
  374.  
  375.     ; convert buffer pointer eax to the absolute address
  376.     mov     ecx, IPBUFFSIZE
  377.     mul     ecx
  378.     add     eax, IPbuffs
  379.  
  380.     mov     edx, eax
  381.  
  382.     mov     [edx + 33], bl            ; TCP flags
  383.  
  384.     mov     ebx, [sktAddr]
  385.  
  386.     ; So, ebx holds the socket ptr, edx holds the IPbuffer ptr
  387.  
  388.     ; Fill in the IP header ( some data is in the socket descriptor)
  389.     mov     eax, [ebx + 8]
  390.     mov     [edx + 12], eax      ; source IP
  391.     mov     eax, [ebx + 16]
  392.     mov     [edx + 16], eax      ; Destination IP
  393.  
  394.     mov     al, 0x45
  395.     mov     [edx], al         ; Version, IHL
  396.     xor     al, al
  397.     mov     [edx + 1], al     ; Type of service
  398.  
  399.     pop     eax                   ; Get the TCP data length
  400.     push    eax
  401.  
  402.     add     eax, 20 + 20           ; add IP header and TCP header lengths
  403.     mov     [edx + 2], ah
  404.     mov     [edx + 3], al
  405.     xor     al, al
  406.     mov     [edx + 4], al
  407.     mov     [edx + 5], al
  408.     mov     al, 0x40
  409.     mov     [edx + 6], al
  410.     xor     al, al
  411.     mov     [edx + 7], al
  412.     mov     al, 0x20
  413.     mov     [edx + 8], al
  414.     mov     al, 6                         ; TCP protocol
  415.     mov     [edx + 9], al
  416.  
  417.     ; Checksum left unfilled
  418.     xor     ax, ax
  419.     mov     [edx + 10], ax
  420.  
  421.     ; Fill in the TCP header ( some data is in the socket descriptor)
  422.     mov     ax, [ebx + 12]
  423.     mov     [edx + 20], ax        ; Local Port
  424.  
  425.     mov     ax, [ebx + 20]
  426.     mov     [edx + 20 + 2], ax    ; desitination Port
  427.  
  428.     ; Checksum left unfilled
  429.     xor     ax, ax
  430.     mov     [edx + 20 + 16], ax
  431.  
  432.     ; sequence number
  433.     mov     eax, [ebx + 48]
  434.     mov     [edx + 20 + 4], eax
  435.  
  436.     ; ack number
  437.     mov     eax, [ebx + 56]
  438.     mov     [edx + 20 + 8], eax
  439.  
  440.     ; window ( 0x2000 is default ).I could accept 4KB, fa0, ( skt buffer size)
  441.     ; 768 bytes seems better
  442.     mov     ax, 0x0003
  443.     mov     [edx + 20 + 14], ax
  444.  
  445.     ; Urgent pointer (0)
  446.     mov     ax, 0
  447.     mov     [edx + 20 + 18], ax
  448.  
  449.     ; data offset ( 0x50 )
  450.     mov     al, 0x50
  451.     mov     [edx + 20 + 12], al
  452.  
  453.     pop     ecx                  ; count of bytes to send
  454.     mov     ebx, ecx            ; need the length later
  455.  
  456.     cmp     ebx, 0
  457.     jz      btp_001
  458.  
  459.     mov     edi, edx
  460.     add     edi, 40
  461.     cld
  462.     rep     movsb               ; copy the data across
  463.  
  464. btp_001:
  465.     ; we have edx as IPbuffer ptr.
  466.     ; Fill in the TCP checksum
  467.     ; First, fill in pseudoheader
  468.     mov     eax, [edx + 12]
  469.     mov     [pseudoHeader], eax
  470.     mov     eax, [edx + 16]
  471.     mov     [pseudoHeader+4], eax
  472.     mov     ax, 0x0600            ; 0 + protocol
  473.     mov     [pseudoHeader+8], ax
  474.     add     ebx, 20
  475.     mov     eax, ebx
  476.     mov     [pseudoHeader+10], ah
  477.     mov     [pseudoHeader+11], al
  478.  
  479.     mov     eax, pseudoHeader
  480.     mov     [checkAdd1], eax
  481.     mov     [checkSize1], word 12
  482.     mov     eax, edx
  483.     add     eax, 20
  484.     mov     [checkAdd2], eax
  485.     mov     eax, ebx
  486.     mov     [checkSize2], ax
  487.  
  488.     call    checksum
  489.  
  490.     ; store it in the TCP checksum ( in the correct order! )
  491.     mov     ax, [checkResult]
  492.  
  493.     mov     [edx + 20 + 16], ah
  494.     mov     [edx + 20 + 17], al
  495.  
  496.     ; Fill in the IP header checksum
  497.     mov     eax, edx
  498.     mov     [checkAdd1], eax
  499.     mov     [checkSize1], word 20
  500.     mov     [checkAdd2], dword 0
  501.     mov     [checkSize2], word 0
  502.  
  503.     call    checksum
  504.  
  505.     mov     ax, [checkResult]
  506.     mov     [edx + 10], ah
  507.     mov     [edx + 11], al
  508.  
  509.     ret
  510.  
  511.  
  512. ; Increments the 32 bit value pointed to by esi in internet order
  513. inc_inet_esi:
  514.     push    eax
  515.     add     esi, 3
  516.     mov     al, byte[esi]
  517.     inc     al
  518.     mov     byte[esi], al
  519.     cmp     al, 0
  520.     jnz     iie_exit
  521.     dec     esi
  522.     mov     al, byte[esi]
  523.     inc     al
  524.     mov     byte[esi], al
  525.     cmp     al, 0
  526.     jnz     iie_exit
  527.     dec     esi
  528.     mov     al, byte[esi]
  529.     inc     al
  530.     mov     byte[esi], al
  531.     cmp     al, 0
  532.     jnz     iie_exit
  533.     dec     esi
  534.     mov     al, byte[esi]
  535.     inc     al
  536.     mov     byte[esi], al
  537.  
  538. iie_exit:
  539.     pop     eax
  540.     ret
  541.  
  542.  
  543. ; Increments the 32 bit value pointed to by esi in internet order
  544. ; by the value in ecx
  545. add_inet_esi:
  546.     push    eax
  547.  
  548.     mov     al, [esi]
  549.     shl     eax, 8
  550.     inc     esi
  551.     mov     al, [esi]
  552.     shl     eax, 8
  553.     inc     esi
  554.     mov     al, [esi]
  555.     shl     eax, 8
  556.     inc     esi
  557.     mov     al, [esi]
  558.     add     eax, ecx
  559.     mov     [esi], al
  560.     dec     esi
  561.     shr     eax, 8
  562.     mov     [esi], al
  563.     dec     esi
  564.     shr     eax, 8
  565.     mov     [esi], al
  566.     dec     esi
  567.     shr     eax, 8
  568.     mov     [esi], al
  569.     pop     eax
  570.     ret
  571.  
  572.  
  573. iglobal
  574.   TCBStateHandler:
  575.     dd      stateTCB_LISTEN
  576.     dd      stateTCB_SYN_SENT
  577.     dd      stateTCB_SYN_RECEIVED
  578.     dd      stateTCB_ESTABLISHED
  579.     dd      stateTCB_FIN_WAIT_1
  580.     dd      stateTCB_FIN_WAIT_2
  581.     dd      stateTCB_CLOSE_WAIT
  582.     dd      stateTCB_CLOSING
  583.     dd      stateTCB_LAST_ACK
  584.     dd      stateTCB_TIME_WAIT
  585.     dd      stateTCB_CLOSED
  586. endg
  587.  
  588. ;***************************************************************************
  589. ;   Function
  590. ;      tcpStateMachine
  591. ;
  592. ;   Description
  593. ;       TCP state machine
  594. ;       This is a kernel function, called by tcp_rx
  595. ;
  596. ;       IP buffer address given in edx
  597. ;          Socket/TCB address in [eax + sockets]
  598. ;
  599. ;       The IP buffer will be released by the caller
  600. ;***************************************************************************
  601. tcpStateMachine:
  602.     mov     ebx, sockets
  603.     add     ebx, eax
  604.     mov     [sktAddr], ebx
  605.  
  606.     ; as a packet has been received, update the TCB timer
  607.     mov     ecx, TWOMSL
  608.     mov     [ebx + 32], ecx
  609.  
  610.     ; If the received packet has an ACK bit set,
  611.     ; remove any packets in the resend queue that this
  612.     ; received packet acknowledges
  613.     pusha
  614.     mov     cl, [edx + 33]
  615.     and     cl, 0x10
  616.     cmp     cl, 0x10
  617.     jne     tsm001                      ; No ACK, so no data yet
  618.  
  619.  
  620.     ; get skt number in al
  621.     shr     eax, 12
  622.  
  623.     ; The ack number is in [edx + 28], inet format
  624.     ; skt in al
  625.  
  626.     mov     esi, resendQ
  627.     mov     ecx, 0
  628.  
  629. t001:
  630.     cmp     ecx, NUMRESENDENTRIES
  631.     je      t003              ; None left
  632.     cmp     [esi], al
  633.     je      t002              ; found one
  634.     inc     ecx
  635.     add     esi, 4
  636.     jmp     t001
  637.  
  638. t002:                   ; Can we delete this buffer?
  639.  
  640.                         ; If yes, goto t004. No, goto t001
  641.     ; Get packet data address
  642.  
  643.     push    ecx
  644.     inc     ecx
  645.     ; Now get buffer location, and copy buffer across. argh! more copying,,
  646.     mov     edi, resendBuffer - IPBUFFSIZE
  647. t002a:
  648.     add     edi, IPBUFFSIZE
  649.     loop    t002a
  650.  
  651.     ; we have dest buffer location in edi. incoming packet in edx.
  652.     ; Get this packets sequence number
  653.     ; preserve al, ecx, esi, edx
  654.  
  655.     mov     cl, [edi + 24]
  656.     shl     ecx, 8
  657.     mov     cl, [edi + 25]
  658.     shl     ecx, 8
  659.     mov     cl, [edi + 26]
  660.     shl     ecx, 8
  661.     mov     cl, [edi + 27]
  662.     movzx   ebx, byte [edi + 3]
  663.     mov     bh, [edi + 2]
  664.     sub     ebx, 40
  665.     add     ecx, ebx          ; ecx is now seq# of last byte +1, intel format
  666.  
  667.     ; get recievd ack #, in intel format
  668.     mov     bl, [edx + 28]
  669.     shl     ebx, 8
  670.     mov     bl, [edx + 29]
  671.     shl     ebx, 8
  672.     mov     bl, [edx + 30]
  673.     shl     ebx, 8
  674.     mov     bl, [edx + 31]
  675.  
  676.     cmp     ebx, ecx        ; Finally. ecx = rx'ed ack. ebx = last byte in que
  677.                             ; DANGER! need to handle case that we have just
  678.                             ; passed the 2**32, and wrapped round!
  679.     pop     ecx
  680.  
  681.     jae     t004             ; if rx > old, delete old
  682.     inc     ecx
  683.     add     esi, 4
  684.     jmp     t001
  685.  
  686.  
  687. t004:
  688.     dec     dword [arp_rx_count] ; ************ TEST ONLY!
  689.  
  690.     mov     [esi], byte 0xFF
  691.     inc     ecx
  692.     add     esi, 4
  693.     jmp     t001
  694.  
  695. t003:
  696.  
  697. tsm001:
  698.     popa
  699.  
  700.     ; Call handler for given TCB state
  701.     mov     ebx, [eax + sockets+28]
  702.     cmp     ebx, TCB_LISTEN
  703.     jb      tsm_exit
  704.     cmp     ebx, TCB_CLOSED
  705.     ja      tsm_exit
  706.  
  707.     dec     ebx
  708.     call    dword [TCBStateHandler+ebx*4]
  709.  
  710. tsm_exit:
  711.     ret
  712.  
  713.  
  714.  
  715. stateTCB_LISTEN:
  716.     ; In this case, we are expecting a SYN packet
  717.     ; For now, if the packet is a SYN, process it, and send a response
  718.     ; If not, ignore it
  719.  
  720.     ; Look at control flags
  721.     mov     bl, [edx + 33]
  722.     and     bl, 0x02
  723.     cmp     bl, 0x02
  724.     jnz     stl_exit
  725.  
  726.     ; We have a SYN. update the socket with this IP packets details,
  727.     ; And send a response
  728.  
  729.     mov     ebx, [edx + 12] ; IP source address
  730.     mov     [eax + sockets + 16], ebx
  731.     mov     bx, [edx + 20] ; IP source port
  732.     mov     [eax + sockets + 20], bx
  733.     mov     ebx, [edx + 24] ; IRS
  734.     mov     [eax + sockets + 40], ebx
  735.     mov     [eax + sockets + 56], ebx
  736.     mov     esi, sockets
  737.     add     esi, eax
  738.     add     esi, 56
  739.     call    inc_inet_esi ; RCV.NXT
  740.     mov     ebx, [eax + sockets + 36]    ; ISS
  741.     mov     [eax + sockets + 48], ebx    ; SND.NXT
  742.  
  743.     ; Now construct the response, and queue for sending by IP
  744.     mov     eax, EMPTY_QUEUE
  745.     call    dequeue
  746.     cmp     ax, NO_BUFFER
  747.     je      stl_exit
  748.  
  749.     push    eax
  750.     mov     bl, 0x12        ; SYN + ACK
  751.     mov     ecx, 0
  752.     mov     esi, 0
  753.  
  754.     call    buildTCPPacket
  755.  
  756.     mov     eax, NET1OUT_QUEUE
  757.     mov     edx, [stack_ip]
  758.     mov     ecx, [ sktAddr ]
  759.     mov     ecx, [ ecx + 16 ]
  760.     cmp     edx, ecx
  761.     jne     stl_notlocal
  762.     mov     eax, IPIN_QUEUE
  763.  
  764. stl_notlocal:
  765.        ; Send it.
  766.     pop     ebx
  767.     call    queue
  768.  
  769.  
  770.     mov     ebx, TCB_SYN_RECEIVED
  771.     mov     esi, [sktAddr]
  772.     mov     [esi + 28], ebx
  773.  
  774.     ; increament SND.NXT in socket
  775.     add     esi, 48
  776.     call    inc_inet_esi
  777.  
  778. stl_exit:
  779.     ret
  780.  
  781.  
  782.  
  783. stateTCB_SYN_SENT:
  784.     ; We are awaiting an ACK to our SYN, with a SYM
  785.     ; Look at control flags - expecting an ACK
  786.     mov     bl, [edx + 33]
  787.     and     bl, 0x12
  788.     cmp     bl, 0x12
  789.     jnz     stss_exit
  790.  
  791.     mov     ebx, TCB_ESTABLISHED
  792.     mov     esi, [sktAddr]
  793.     mov     [esi + 28], ebx
  794.  
  795.     ; Store the recv.nxt field
  796.     mov     eax, [edx + 24]
  797.  
  798.     ; Update our recv.nxt field
  799.     mov     esi, [sktAddr]
  800.     add     esi, 56
  801.     mov     [esi], eax
  802.     call    inc_inet_esi
  803.  
  804.     ; Send an ACK
  805.     ; Now construct the response, and queue for sending by IP
  806.     mov     eax, EMPTY_QUEUE
  807.     call    dequeue
  808.     cmp     ax, NO_BUFFER
  809.     je      stss_exit
  810.  
  811.     push    eax
  812.  
  813.     mov     bl, 0x10        ; ACK
  814.     mov     ecx, 0
  815.     mov     esi, 0
  816.  
  817.     call    buildTCPPacket
  818.  
  819.     mov     eax, NET1OUT_QUEUE
  820.  
  821.     mov     edx, [stack_ip]
  822.     mov     ecx, [ sktAddr ]
  823.     mov     ecx, [ ecx + 16 ]
  824.     cmp     edx, ecx
  825.     jne     stss_notlocal
  826.     mov     eax, IPIN_QUEUE
  827.  
  828. stss_notlocal:
  829.        ; Send it.
  830.     pop     ebx
  831.     call    queue
  832.  
  833. stss_exit:
  834.     ret
  835.  
  836.  
  837.  
  838. stateTCB_SYN_RECEIVED:
  839.     ; In this case, we are expecting an ACK packet
  840.     ; For now, if the packet is an ACK, process it,
  841.     ; If not, ignore it
  842.  
  843.     ; Look at control flags - expecting an ACK
  844.     mov     bl, [edx + 33]
  845.     and     bl, 0x10
  846.     cmp     bl, 0x10
  847.     jnz     stsr_exit
  848.  
  849.     mov     ebx, TCB_ESTABLISHED
  850.     mov     esi, [sktAddr]
  851.     mov     [esi + 28], ebx
  852.  
  853. stsr_exit:
  854.     ret
  855.  
  856.  
  857.  
  858. stateTCB_ESTABLISHED:
  859.     ; Here we are expecting data, or a request to close
  860.     ; OR both...
  861.  
  862.     ; Did we receive a FIN or RST?
  863.     mov     bl, [edx + 33]
  864.     and     bl, 0x05
  865.     cmp     bl, 0
  866.     je      ste_chkack
  867.  
  868.     ; It was a fin or reset.
  869.  
  870.     ; Remove resend entries from the queue  - I dont want to send any more data
  871.     pusha
  872.  
  873.     mov     ebx, [sktAddr]
  874.     sub     ebx, sockets
  875.     shr     ebx, 12             ; get skt #
  876.  
  877.     mov     esi, resendQ
  878.     mov     ecx, 0
  879.  
  880. ste001:
  881.     cmp     ecx, NUMRESENDENTRIES
  882.     je      ste003              ; None left
  883.     cmp     [esi], bl
  884.     je      ste002              ; found one
  885.     inc     ecx
  886.     add     esi, 4
  887.     jmp     ste001
  888.  
  889. ste002:
  890.     dec     dword [arp_rx_count] ; ************ TEST ONLY!
  891.  
  892.     mov     [esi], byte 0xFF
  893.     jmp     ste001
  894.  
  895. ste003:
  896.     popa
  897.  
  898.     ; was it a reset?
  899.     mov     bl, [edx + 33]
  900.     and     bl, 0x04
  901.     cmp     bl, 0x04
  902.     jne     ste003a
  903.  
  904.     mov     esi, [sktAddr]
  905.     mov     ebx, TCB_CLOSED
  906.     mov     [esi + 28], ebx
  907.     jmp     ste_exit
  908.  
  909. ste003a:
  910.     ; Send an ACK to that fin, and enter closewait state
  911.  
  912.     mov     esi, [sktAddr]
  913.     mov     ebx, TCB_CLOSE_WAIT
  914.     mov     [esi + 28], ebx
  915.     add     esi, 56
  916.     mov     eax, [esi]              ; save original
  917.     call    inc_inet_esi
  918.     ;; jmp    ste_ack - NO, there may be data
  919.  
  920. ste_chkack:
  921.     ; Check that we received an ACK
  922.     mov     bl, [edx + 33]
  923.     and     bl, 0x10
  924.     cmp     bl, 0x10
  925.     jnz     ste_exit
  926.  
  927.  
  928.     ; TODO - done, I think!
  929.     ; First, look at the incoming window. If this is less than or equal to 1024,
  930.     ; Set the socket window timer to 1. This will stop an additional packets being
  931.     ; queued.
  932.     ; ** I may need to tweak this value, since I do not know how many packets are already queued
  933.     mov     ch, [edx + 34]
  934.     mov     cl, [edx + 35]
  935.     cmp     cx, 1024
  936.     ja      ste004
  937.  
  938.     mov     ecx, [sktAddr]
  939.     mov     [ecx+72], dword 1
  940.  
  941. ste004:
  942.  
  943.     ; OK, here is the deal
  944.     ; My recv.nct field holds the seq of the expected next rec byte
  945.     ; if the recevied sequence number is not equal to this, do not
  946.     ; increment the recv.nxt field, do not copy data - just send a
  947.     ; repeat ack.
  948.  
  949.     ; recv.nxt is in dword [edx+24], in inext format
  950.     ; recv seq is in [sktAddr]+56, in inet format
  951.     ; just do a comparision
  952.     mov     ecx, [sktAddr]
  953.     add     ecx, 56
  954.  
  955.     cmp     [ecx - 56 + 28], dword TCB_CLOSE_WAIT
  956.     mov     ecx, [ecx]
  957.     jne     stenofin
  958.     mov     ecx, eax
  959.  
  960. stenofin:
  961.     cmp     ecx, [edx+24]
  962.     jne     ste_ack
  963.  
  964.  
  965.     ; Read the data bytes, store in socket buffer
  966.     xor     ecx, ecx
  967.     mov     ch, [edx + 2]
  968.     mov     cl, [edx + 3]
  969.     sub     ecx, 40                    ; Discard 40 bytes of header
  970.  
  971.     cmp     ecx, 0
  972.     jnz     ste_data                ; Read data, if any
  973.  
  974.     ; If we had received a fin, we need to ACK it.
  975.     mov     esi, [sktAddr]
  976.     mov     ebx, [esi + 28]
  977.     cmp     ebx, TCB_CLOSE_WAIT
  978.     jz      ste_ack
  979.     jnz     ste_exit
  980.  
  981. ste_data:
  982.     push    ecx
  983.     mov     esi, [sktAddr]
  984.  
  985.     add     [esi + 24], ecx      ; increment the count of bytes in buffer
  986.  
  987.     mov     eax, [esi + 4]       ; get socket owner PID
  988.     push    eax
  989.  
  990.     mov     eax, [esi + 24]      ; get # of bytes already in buffer
  991.  
  992.     ; point to the location to store the data
  993.     add     esi, eax
  994.     sub     esi, ecx
  995.     add     esi, SOCKETHEADERSIZE
  996.  
  997.     add     edx, 40        ; edx now points to the data
  998.     mov     edi, esi
  999.     mov     esi, edx
  1000.  
  1001.     cld
  1002.     rep     movsb          ; copy the data across
  1003.  
  1004.     ; flag an event to the application
  1005.     pop     eax
  1006.     mov     ecx,1
  1007.     mov     esi,0x3020+TASKDATA.pid
  1008.  
  1009. news:
  1010.     cmp     [esi],eax
  1011.     je      foundPID1
  1012.     inc     ecx
  1013.     add     esi,0x20
  1014.     cmp     ecx,[0x3004]
  1015.     jbe     news
  1016.  
  1017. foundPID1:
  1018.     shl     ecx,8
  1019.     or      dword [ecx+0x80000+APPDATA.event_mask],dword 10000000b ; stack event
  1020.  
  1021.     pop     ecx
  1022.  
  1023.     ; Update our recv.nxt field
  1024.     mov     esi, [sktAddr]
  1025.     add     esi, 56
  1026.     call    add_inet_esi
  1027.  
  1028. ste_ack:
  1029.     ; Send an ACK
  1030.     ; Now construct the response, and queue for sending by IP
  1031.     mov     eax, EMPTY_QUEUE
  1032.     call    dequeue
  1033.     cmp     ax, NO_BUFFER
  1034.     je      ste_exit
  1035.  
  1036.     push    eax
  1037.  
  1038.     mov     bl, 0x10        ; ACK
  1039.     mov     ecx, 0
  1040.     mov     esi, 0
  1041.  
  1042.     call    buildTCPPacket
  1043.  
  1044.     mov     eax, NET1OUT_QUEUE
  1045.  
  1046.     mov     edx, [stack_ip]
  1047.     mov     ecx, [ sktAddr ]
  1048.     mov     ecx, [ ecx + 16 ]
  1049.     cmp     edx, ecx
  1050.     jne     ste_notlocal
  1051.     mov     eax, IPIN_QUEUE
  1052. ste_notlocal:
  1053.  
  1054.        ; Send it.
  1055.     pop     ebx
  1056.     call    queue
  1057.  
  1058. ste_exit:
  1059.     ret
  1060.  
  1061.  
  1062.  
  1063. stateTCB_FIN_WAIT_1:
  1064.     ; We can either receive an ACK of a fin, or a fin
  1065.     mov     bl, [edx + 33]
  1066.     and     bl, 0x10
  1067.     cmp     bl, 0x10
  1068.     jnz     stfw1_001
  1069.  
  1070.     ; It was an ACK
  1071.     mov     esi, [sktAddr]
  1072.     mov     ebx, TCB_FIN_WAIT_2
  1073.     mov     [esi + 28], ebx
  1074.     jmp     stfw1_exit
  1075.  
  1076. stfw1_001:
  1077.     ; It must be a fin then
  1078.     mov     esi, [sktAddr]
  1079.     mov     ebx, TCB_CLOSING
  1080.     mov     [esi + 28], ebx
  1081.     add     esi, 56
  1082.     call    inc_inet_esi
  1083.  
  1084.     ; Send an ACK
  1085.     mov     eax, EMPTY_QUEUE
  1086.     call    dequeue
  1087.     cmp     ax, NO_BUFFER
  1088.     je      stfw1_exit
  1089.  
  1090.     push    eax
  1091.  
  1092.     mov     bl, 0x10        ; ACK
  1093.     mov     ecx, 0
  1094.     mov     esi, 0
  1095.  
  1096.     call    buildTCPPacket
  1097.     mov     eax, NET1OUT_QUEUE
  1098.  
  1099.     mov     edx, [stack_ip]
  1100.     mov     ecx, [ sktAddr ]
  1101.     mov     ecx, [ ecx + 16 ]
  1102.     cmp     edx, ecx
  1103.     jne     stfw1_notlocal
  1104.     mov     eax, IPIN_QUEUE
  1105.  
  1106. stfw1_notlocal:
  1107.     ; Send it.
  1108.     pop     ebx
  1109.     call    queue
  1110.  
  1111. stfw1_exit:
  1112.     ret
  1113.  
  1114.  
  1115.  
  1116. stateTCB_FIN_WAIT_2:
  1117.     mov     esi, [sktAddr]
  1118.  
  1119.     ; Get data length
  1120.     xor     ecx, ecx
  1121.     mov     ch, [edx+2]
  1122.     mov     cl, [edx+3]
  1123.     sub     ecx, 40
  1124.  
  1125.     mov     bl, [edx + 33]
  1126.     and     bl, 0x01
  1127.     cmp     bl, 0x01
  1128.     jne     stfw2001
  1129.  
  1130.     ; Change state, as we have a fin
  1131.     mov     ebx, TCB_TIME_WAIT
  1132.     mov     [esi + 28], ebx
  1133.  
  1134.     inc     ecx                     ; FIN is part of the sequence space
  1135.  
  1136. stfw2001:
  1137.     add     esi, 56
  1138.     call    add_inet_esi
  1139.  
  1140.     ; Send an ACK
  1141.     mov     eax, EMPTY_QUEUE
  1142.     call    dequeue
  1143.     cmp     ax, NO_BUFFER
  1144.     je      stfw2_exit
  1145.  
  1146.     push    eax
  1147.  
  1148.     mov     bl, 0x10        ; ACK
  1149.     mov     ecx, 0
  1150.     mov     esi, 0
  1151.  
  1152.     call    buildTCPPacket
  1153.  
  1154.     mov     eax, NET1OUT_QUEUE
  1155.  
  1156.     mov     edx, [stack_ip]
  1157.     mov     ecx, [ sktAddr ]
  1158.     mov     ecx, [ ecx + 16 ]
  1159.     cmp     edx, ecx
  1160.     jne     stfw2_notlocal
  1161.     mov     eax, IPIN_QUEUE
  1162.  
  1163. stfw2_notlocal:
  1164.        ; Send it.
  1165.     pop     ebx
  1166.     call    queue
  1167.  
  1168.     ; Only delete the socket if we received the FIN
  1169.  
  1170.     mov     bl, [edx + 33]
  1171.     and     bl, 0x01
  1172.     cmp     bl, 0x01
  1173.     jne     stfw2_exit
  1174.  
  1175. ;    mov     edi, [sktAddr]
  1176.  
  1177.     ; delete the socket. Should really wait for 2MSL
  1178. ;    xor     eax, eax
  1179. ;    mov     ecx,SOCKETHEADERSIZE
  1180. ;    cld
  1181. ;    rep     stosb
  1182.  
  1183. stfw2_exit:
  1184.     ret
  1185.  
  1186.  
  1187.  
  1188. stateTCB_CLOSE_WAIT:
  1189.     ; Intentionally left empty
  1190.     ; socket_close_tcp handles this
  1191.     ret
  1192.  
  1193.  
  1194.  
  1195. stateTCB_CLOSING:
  1196.     ; We can either receive an ACK of a fin, or a fin
  1197.     mov     bl, [edx + 33]
  1198.     and     bl, 0x10
  1199.     cmp     bl, 0x10
  1200.     jnz     stc_exit
  1201.  
  1202.     ; It was an ACK
  1203.  
  1204.     mov     edi, [sktAddr]
  1205.  
  1206.     ; delete the socket
  1207.     xor     eax, eax
  1208.     mov     ecx,SOCKETHEADERSIZE
  1209.     cld
  1210.     rep     stosb
  1211.  
  1212. stc_exit:
  1213.     ret
  1214.  
  1215.  
  1216.  
  1217. stateTCB_LAST_ACK:
  1218.     ; Look at control flags - expecting an ACK
  1219.     mov     bl, [edx + 33]
  1220.     and     bl, 0x10
  1221.     cmp     bl, 0x10
  1222.     jnz     stla_exit
  1223.  
  1224.     mov     edi, [sktAddr]
  1225.  
  1226.     ; delete the socket
  1227.     xor     eax, eax
  1228.     mov     ecx,SOCKETHEADERSIZE
  1229.     cld
  1230.     rep     stosb
  1231.  
  1232. stla_exit:
  1233.     ret
  1234.  
  1235.  
  1236.  
  1237. stateTCB_TIME_WAIT:
  1238.     ret
  1239.  
  1240.  
  1241.  
  1242. stateTCB_CLOSED:
  1243.     ret
  1244.