Subversion Repositories Kolibri OS

Rev

Rev 6910 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
3545 hidnplayr 1
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2
;;                                                                 ;;
6910 hidnplayr 3
;; Copyright (C) KolibriOS team 2004-2017. All rights reserved.    ;;
3545 hidnplayr 4
;; Distributed under terms of the GNU General Public License       ;;
5
;;                                                                 ;;
6
;;  Part of the TCP/IP network stack for KolibriOS                 ;;
7
;;                                                                 ;;
8
;;   Written by hidnplayr@kolibrios.org                            ;;
9
;;                                                                 ;;
5133 hidnplayr 10
;;    Based on the algorithms used in 4.4BSD                       ;;
3545 hidnplayr 11
;;                                                                 ;;
12
;;          GNU GENERAL PUBLIC LICENSE                             ;;
13
;;             Version 2, June 1991                                ;;
14
;;                                                                 ;;
15
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
16
 
4850 mario79 17
$Revision: 6915 $
3545 hidnplayr 18
 
6476 hidnplayr 19
TCP_BIT_NEEDOUTPUT      = 1 shl 0
20
TCP_BIT_TIMESTAMP       = 1 shl 1
21
TCP_BIT_DROPSOCKET      = 1 shl 2
22
TCP_BIT_FIN_IS_ACKED    = 1 shl 3
23
 
5976 hidnplayr 24
;-----------------------------------------------------------------;
25
;                                                                 ;
26
; TCP_input: Add a segment to the incoming TCP queue.             ;
27
;                                                                 ;
28
;  IN:  [esp] = ptr to buffer                                     ;
29
;       ebx = ptr to device struct                                ;
30
;       ecx = TCP segment size                                    ;
31
;       edx = ptr to IPv4 header                                  ;
32
;       esi = ptr to TCP segment                                  ;
33
;       edi = interface number*4                                  ;
34
;                                                                 ;
35
;  OUT: /                                                         ;
36
;                                                                 ;
37
;-----------------------------------------------------------------;
3545 hidnplayr 38
align 4
6011 hidnplayr 39
tcp_input:
6908 ashmew2 40
 
3545 hidnplayr 41
; record the current time
5522 hidnplayr 42
        push    [timer_ticks]           ; in 1/100 seconds
5842 hidnplayr 43
        push    ebx ecx esi edx         ; mind the order (see TCP_queue_entry struct)
3545 hidnplayr 44
        mov     esi, esp
45
 
5842 hidnplayr 46
        push    edi
3545 hidnplayr 47
        add_to_queue TCP_queue, TCP_QUEUE_SIZE, sizeof.TCP_queue_entry, .fail
5842 hidnplayr 48
        pop     edi
3545 hidnplayr 49
        add     esp, sizeof.TCP_queue_entry
50
 
3644 hidnplayr 51
        inc     [TCP_segments_rx + edi]
52
 
3545 hidnplayr 53
        xor     edx, edx
54
        mov     eax, [TCP_input_event]
55
        mov     ebx, [eax + EVENT.id]
56
        xor     esi, esi
57
        call    raise_event
58
 
59
        ret
60
 
61
  .fail:
5842 hidnplayr 62
        pop     edi
3556 hidnplayr 63
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP incoming queue is full, discarding packet!\n"
3545 hidnplayr 64
 
6011 hidnplayr 65
        call    net_ptr_to_num4
3644 hidnplayr 66
        inc     [TCP_segments_missed + edi]
3545 hidnplayr 67
 
5841 hidnplayr 68
        add     esp, sizeof.TCP_queue_entry - 4
6011 hidnplayr 69
        call    net_buff_free
3545 hidnplayr 70
        ret
71
 
72
 
6476 hidnplayr 73
;-----------------------------------------------------------------;
74
;                                                                 ;
75
; TCP_process_input: Process segments from the incoming TCP queue.;
76
;                                                                 ;
77
;  IN:  /                                                         ;
78
;  OUT: /                                                         ;
79
;                                                                 ;
80
;-----------------------------------------------------------------;
3545 hidnplayr 81
align 4
6011 hidnplayr 82
proc tcp_process_input
3545 hidnplayr 83
 
4339 hidnplayr 84
locals
85
        dataoffset      dd ?
4344 hidnplayr 86
        timestamp       dd ?
4347 hidnplayr 87
        temp_bits       db ?
6910 hidnplayr 88
        device          dd ?
4339 hidnplayr 89
endl
90
 
3545 hidnplayr 91
        xor     esi, esi
92
        mov     ecx, MANUAL_DESTROY
93
        call    create_event
94
        mov     [TCP_input_event], eax
95
 
96
  .wait:
97
        mov     eax, [TCP_input_event]
98
        mov     ebx, [eax + EVENT.id]
99
        call    wait_event
100
 
101
  .loop:
102
        get_from_queue TCP_queue, TCP_QUEUE_SIZE, sizeof.TCP_queue_entry, .wait
103
 
104
        push    [esi + TCP_queue_entry.timestamp]
4344 hidnplayr 105
        pop     [timestamp]
3545 hidnplayr 106
        push    [esi + TCP_queue_entry.buffer_ptr]
107
 
108
        mov     ebx, [esi + TCP_queue_entry.device_ptr]
6910 hidnplayr 109
        mov     [device], ebx
3545 hidnplayr 110
        mov     ecx, [esi + TCP_queue_entry.segment_size]
6910 hidnplayr 111
        mov     edi, [esi + TCP_queue_entry.ip_ptr]     ; ptr to ipv4 header
3545 hidnplayr 112
        mov     esi, [esi + TCP_queue_entry.segment_ptr]                ; change esi last
113
 
6908 ashmew2 114
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_input: size=%u time=%d\n", ecx, [timer_ticks]
3545 hidnplayr 115
 
116
        mov     edx, esi
117
 
6476 hidnplayr 118
; Verify the checksum (if not already done by hw)
3545 hidnplayr 119
 
4388 hidnplayr 120
        test    [ebx + NET_DEVICE.hwacc], NET_HWACC_TCP_IPv4_IN
121
        jnz     .checksum_ok
3545 hidnplayr 122
 
123
        push    ecx esi
124
        pushw   [esi + TCP_header.Checksum]
125
        mov     [esi + TCP_header.Checksum], 0
6011 hidnplayr 126
        tcp_checksum (edi+IPv4_header.SourceAddress), (edi+IPv4_header.DestinationAddress)
5842 hidnplayr 127
        pop     cx                              ; previous checksum
3545 hidnplayr 128
        cmp     cx, dx
129
        pop     edx ecx
130
        jne     .drop_no_socket
131
  .checksum_ok:
132
 
133
; Verify the data offset
6476 hidnplayr 134
 
4339 hidnplayr 135
        movzx   eax, [edx + TCP_header.DataOffset]
136
        and     al, 0xf0                        ; Calculate TCP segment header size (throwing away unused reserved bits in TCP header)
137
        shr     al, 2
138
        cmp     al, sizeof.TCP_header           ; Now see if it's at least the size of a standard TCP header
139
        jb      .drop_no_socket                 ; If not, drop the packet
140
        mov     [dataoffset], eax
3545 hidnplayr 141
 
142
        sub     ecx, eax                                                ; substract TCP header size from total segment size
143
        jb      .drop_no_socket                                         ; If total segment size is less then the advertised header size, drop packet
6908 ashmew2 144
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_input: %u bytes of data\n", ecx
3545 hidnplayr 145
 
146
;-------------------------------------------
147
; Convert Big-endian values to little endian
148
 
149
        ntohd   [edx + TCP_header.SequenceNumber]
150
        ntohd   [edx + TCP_header.AckNumber]
151
 
152
        ntohw   [edx + TCP_header.Window]
153
        ntohw   [edx + TCP_header.UrgentPointer]
154
 
6476 hidnplayr 155
;-----------------------------------------------------------------------------------
156
;
3545 hidnplayr 157
; Find the socket pointer
6476 hidnplayr 158
;
159
;-----------------------------------------------------------------------------------
3545 hidnplayr 160
 
161
; IP Packet TCP Destination Port = local Port
162
; (IP Packet SenderAddress = Remote IP)  OR  (Remote IP = 0)
163
; (IP Packet TCP Source Port = remote Port) OR (remote Port = 0)
164
 
165
  .findpcb:
3647 hidnplayr 166
        pusha
167
        mov     ecx, socket_mutex
168
        call    mutex_lock
169
        popa
170
 
3545 hidnplayr 171
        mov     ebx, net_sockets
172
        mov     si, [edx + TCP_header.DestinationPort]
173
 
174
  .socket_loop:
175
        mov     ebx, [ebx + SOCKET.NextPtr]
176
        or      ebx, ebx
3647 hidnplayr 177
        jz      .no_socket ;respond_seg_reset
3545 hidnplayr 178
 
179
        cmp     [ebx + SOCKET.Domain], AF_INET4
180
        jne     .socket_loop
181
 
182
        cmp     [ebx + SOCKET.Protocol], IP_PROTO_TCP
183
        jne     .socket_loop
184
 
185
        cmp     [ebx + TCP_SOCKET.LocalPort], si
186
        jne     .socket_loop
187
 
188
        mov     eax, [ebx + IP_SOCKET.RemoteIP]
5842 hidnplayr 189
        cmp     eax, [edi + IPv4_header.SourceAddress]
3545 hidnplayr 190
        je      @f
191
        test    eax, eax
192
        jnz     .socket_loop
193
       @@:
194
 
195
        mov     ax, [ebx + TCP_SOCKET.RemotePort]
196
        cmp     [edx + TCP_header.SourcePort], ax
197
        je      .found_socket
198
        test    ax, ax
199
        jnz     .socket_loop
200
  .found_socket:                                        ; ebx now contains the socketpointer