Subversion Repositories Kolibri OS

Rev

Rev 5565 | Go to most recent revision | Only display areas with differences | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 5565 Rev 5984
1
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2
;;                                                                 ;;
2
;;                                                                 ;;
3
;; Copyright (C) KolibriOS team 2004-2015. All rights reserved.    ;;
3
;; Copyright (C) KolibriOS team 2004-2015. All rights reserved.    ;;
4
;; Distributed under terms of the GNU General Public License       ;;
4
;; Distributed under terms of the GNU General Public License       ;;
5
;;                                                                 ;;
5
;;                                                                 ;;
6
;;  Part of the TCP/IP network stack for KolibriOS                 ;;
6
;;  Part of the TCP/IP network stack for KolibriOS                 ;;
7
;;                                                                 ;;
7
;;                                                                 ;;
8
;;   Written by hidnplayr@kolibrios.org                            ;;
8
;;   Written by hidnplayr@kolibrios.org                            ;;
9
;;                                                                 ;;
9
;;                                                                 ;;
10
;;    Based on the algorithms used in 4.4BSD                       ;;
10
;;    Based on the algorithms used in 4.4BSD                       ;;
11
;;                                                                 ;;
11
;;                                                                 ;;
12
;;          GNU GENERAL PUBLIC LICENSE                             ;;
12
;;          GNU GENERAL PUBLIC LICENSE                             ;;
13
;;             Version 2, June 1991                                ;;
13
;;             Version 2, June 1991                                ;;
14
;;                                                                 ;;
14
;;                                                                 ;;
15
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
15
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
16
 
16
 
17
$Revision: 5522 $
-
 
18
 
-
 
19
;-----------------------------------------------------------------
-
 
20
;
-
 
21
; TCP_input:
-
 
22
;
-
 
23
;       Add a segment to the incoming TCP queue
-
 
24
;
-
 
25
;  IN:  [esp] = ptr to buffer
-
 
26
;       ebx = ptr to device struct
-
 
27
;       ecx = segment size
-
 
28
;       esi = ptr to TCP segment
-
 
29
;       edi = ptr to ipv4 source address, followed by ipv4 dest address
-
 
30
;
-
 
31
;  OUT: /
-
 
32
;
-
 
-
 
17
$Revision: 5976 $
-
 
18
 
-
 
19
;-----------------------------------------------------------------;
-
 
20
;                                                                 ;
-
 
21
; TCP_input: Add a segment to the incoming TCP queue.             ;
-
 
22
;                                                                 ;
-
 
23
;  IN:  [esp] = ptr to buffer                                     ;
-
 
24
;       ebx = ptr to device struct                                ;
-
 
25
;       ecx = TCP segment size                                    ;
-
 
26
;       edx = ptr to IPv4 header                                  ;
-
 
27
;       esi = ptr to TCP segment                                  ;
-
 
28
;       edi = interface number*4                                  ;
-
 
29
;                                                                 ;
-
 
30
;  OUT: /                                                         ;
33
;-----------------------------------------------------------------
31
;                                                                 ;
34
 
32
;-----------------------------------------------------------------;
35
align 4
33
align 4
36
TCP_input:
34
TCP_input:
37
 
35
 
38
; record the current time
36
; record the current time
39
        push    [timer_ticks]           ; in 1/100 seconds
37
        push    [timer_ticks]           ; in 1/100 seconds
40
        push    ebx ecx esi edi         ; mind the order (see TCP_queue_entry struct)
38
        push    ebx ecx esi edx         ; mind the order (see TCP_queue_entry struct)
41
        mov     esi, esp
39
        mov     esi, esp
-
 
40
 
42
 
41
        push    edi
-
 
42
        add_to_queue TCP_queue, TCP_QUEUE_SIZE, sizeof.TCP_queue_entry, .fail
43
        add_to_queue TCP_queue, TCP_QUEUE_SIZE, sizeof.TCP_queue_entry, .fail
43
        pop     edi
44
        add     esp, sizeof.TCP_queue_entry
-
 
45
 
44
        add     esp, sizeof.TCP_queue_entry
46
        call    NET_ptr_to_num4
45
 
47
        inc     [TCP_segments_rx + edi]
46
        inc     [TCP_segments_rx + edi]
48
 
47
 
49
        xor     edx, edx
48
        xor     edx, edx
50
        mov     eax, [TCP_input_event]
49
        mov     eax, [TCP_input_event]
51
        mov     ebx, [eax + EVENT.id]
50
        mov     ebx, [eax + EVENT.id]
52
        xor     esi, esi
51
        xor     esi, esi
53
        call    raise_event
52
        call    raise_event
54
 
53
 
55
        ret
54
        ret
56
 
55
 
57
  .fail:
56
  .fail:
-
 
57
        pop     edi
58
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP incoming queue is full, discarding packet!\n"
58
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP incoming queue is full, discarding packet!\n"
59
 
59
 
60
        call    NET_ptr_to_num4
60
        call    NET_ptr_to_num4
61
        inc     [TCP_segments_missed + edi]
61
        inc     [TCP_segments_missed + edi]
62
 
62
 
63
        add     esp, sizeof.TCP_queue_entry - 8
63
        add     esp, sizeof.TCP_queue_entry - 4
64
        call    NET_BUFF_free
64
        call    NET_BUFF_free
65
        ret
65
        ret
66
 
66
 
67
 
67
 
68
 
68
 
69
align 4
69
align 4
70
proc TCP_process_input
70
proc TCP_process_input
71
 
71
 
72
locals
72
locals
73
        dataoffset      dd ?
73
        dataoffset      dd ?
74
        timestamp       dd ?
74
        timestamp       dd ?
75
        temp_bits       db ?
75
        temp_bits       db ?
76
endl
76
endl
77
 
77
 
78
        xor     esi, esi
78
        xor     esi, esi
79
        mov     ecx, MANUAL_DESTROY
79
        mov     ecx, MANUAL_DESTROY
80
        call    create_event
80
        call    create_event
81
        mov     [TCP_input_event], eax
81
        mov     [TCP_input_event], eax
82
 
82
 
83
  .wait:
83
  .wait:
84
        mov     eax, [TCP_input_event]
84
        mov     eax, [TCP_input_event]
85
        mov     ebx, [eax + EVENT.id]
85
        mov     ebx, [eax + EVENT.id]
86
        call    wait_event
86
        call    wait_event
87
 
87
 
88
  .loop:
88
  .loop:
89
        get_from_queue TCP_queue, TCP_QUEUE_SIZE, sizeof.TCP_queue_entry, .wait
89
        get_from_queue TCP_queue, TCP_QUEUE_SIZE, sizeof.TCP_queue_entry, .wait
90
 
90
 
91
        push    [esi + TCP_queue_entry.timestamp]
91
        push    [esi + TCP_queue_entry.timestamp]
92
        pop     [timestamp]
92
        pop     [timestamp]
93
        push    [esi + TCP_queue_entry.buffer_ptr]
93
        push    [esi + TCP_queue_entry.buffer_ptr]
94
 
94
 
95
        mov     ebx, [esi + TCP_queue_entry.device_ptr]
95
        mov     ebx, [esi + TCP_queue_entry.device_ptr]
96
        mov     ecx, [esi + TCP_queue_entry.segment_size]
96
        mov     ecx, [esi + TCP_queue_entry.segment_size]
97
        mov     edi, [esi + TCP_queue_entry.ip_ptr]                     ; ptr to ipv4 source address, followed by ipv4 destination address
97
        mov     edi, [esi + TCP_queue_entry.ip_ptr]                     ; ptr to ipv4 header
98
        mov     esi, [esi + TCP_queue_entry.segment_ptr]                ; change esi last
98
        mov     esi, [esi + TCP_queue_entry.segment_ptr]                ; change esi last
99
 
99
 
100
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_input: size=%u time=%d\n", ecx, [timer_ticks]
100
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_input: size=%u time=%d\n", ecx, [timer_ticks]
101
 
101
 
102
        mov     edx, esi
102
        mov     edx, esi
103
 
103
 
104
        cmp     ebx, LOOPBACK_DEVICE
104
        cmp     ebx, LOOPBACK_DEVICE
105
        je      .checksum_ok
105
        je      .checksum_ok
106
 
106
 
107
; re-calculate the checksum (if not already done by hw)
107
; re-calculate the checksum (if not already done by hw)
108
        test    [ebx + NET_DEVICE.hwacc], NET_HWACC_TCP_IPv4_IN
108
        test    [ebx + NET_DEVICE.hwacc], NET_HWACC_TCP_IPv4_IN
109
        jnz     .checksum_ok
109
        jnz     .checksum_ok
110
 
110
 
111
        push    ecx esi
111
        push    ecx esi
112
        pushw   [esi + TCP_header.Checksum]
112
        pushw   [esi + TCP_header.Checksum]
113
        mov     [esi + TCP_header.Checksum], 0
113
        mov     [esi + TCP_header.Checksum], 0
114
        TCP_checksum (edi), (edi+4)
114
        TCP_checksum (edi+IPv4_header.SourceAddress), (edi+IPv4_header.DestinationAddress)
115
        pop     cx                      ; previous checksum
115
        pop     cx                              ; previous checksum
116
        cmp     cx, dx
116
        cmp     cx, dx
117
        pop     edx ecx
117
        pop     edx ecx
118
        jne     .drop_no_socket
118
        jne     .drop_no_socket
119
  .checksum_ok:
119
  .checksum_ok:
120
 
120
 
121
; Verify the data offset
121
; Verify the data offset
122
        movzx   eax, [edx + TCP_header.DataOffset]
122
        movzx   eax, [edx + TCP_header.DataOffset]
123
        and     al, 0xf0                        ; Calculate TCP segment header size (throwing away unused reserved bits in TCP header)
123
        and     al, 0xf0                        ; Calculate TCP segment header size (throwing away unused reserved bits in TCP header)
124
        shr     al, 2
124
        shr     al, 2
125
        cmp     al, sizeof.TCP_header           ; Now see if it's at least the size of a standard TCP header
125
        cmp     al, sizeof.TCP_header           ; Now see if it's at least the size of a standard TCP header
126
        jb      .drop_no_socket                 ; If not, drop the packet
126
        jb      .drop_no_socket                 ; If not, drop the packet
127
        mov     [dataoffset], eax
127
        mov     [dataoffset], eax
128
 
128
 
129
        sub     ecx, eax                                                ; substract TCP header size from total segment size
129
        sub     ecx, eax                                                ; substract TCP header size from total segment size
130
        jb      .drop_no_socket                                         ; If total segment size is less then the advertised header size, drop packet
130
        jb      .drop_no_socket                                         ; If total segment size is less then the advertised header size, drop packet
131
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_input: %u bytes of data\n", ecx
131
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_input: %u bytes of data\n", ecx
132
 
132
 
133
;-------------------------------------------
133
;-------------------------------------------
134
; Convert Big-endian values to little endian
134
; Convert Big-endian values to little endian
135
 
135
 
136
        ntohd   [edx + TCP_header.SequenceNumber]
136
        ntohd   [edx + TCP_header.SequenceNumber]
137
        ntohd   [edx + TCP_header.AckNumber]
137
        ntohd   [edx + TCP_header.AckNumber]
138
 
138
 
139
        ntohw   [edx + TCP_header.Window]
139
        ntohw   [edx + TCP_header.Window]
140
        ntohw   [edx + TCP_header.UrgentPointer]
140
        ntohw   [edx + TCP_header.UrgentPointer]
141
 
141
 
142
;------------------------
142
;------------------------
143
; Find the socket pointer
143
; Find the socket pointer
144
 
144
 
145
; IP Packet TCP Destination Port = local Port
145
; IP Packet TCP Destination Port = local Port
146
; (IP Packet SenderAddress = Remote IP)  OR  (Remote IP = 0)
146
; (IP Packet SenderAddress = Remote IP)  OR  (Remote IP = 0)
147
; (IP Packet TCP Source Port = remote Port) OR (remote Port = 0)
147
; (IP Packet TCP Source Port = remote Port) OR (remote Port = 0)
148
 
148
 
149
  .findpcb:
149
  .findpcb:
150
        pusha
150
        pusha
151
        mov     ecx, socket_mutex
151
        mov     ecx, socket_mutex
152
        call    mutex_lock
152
        call    mutex_lock
153
        popa
153
        popa
154
 
154
 
155
        mov     ebx, net_sockets
155
        mov     ebx, net_sockets
156
        mov     si, [edx + TCP_header.DestinationPort]
156
        mov     si, [edx + TCP_header.DestinationPort]
157
 
157
 
158
  .socket_loop:
158
  .socket_loop:
159
        mov     ebx, [ebx + SOCKET.NextPtr]
159
        mov     ebx, [ebx + SOCKET.NextPtr]
160
        or      ebx, ebx
160
        or      ebx, ebx
161
        jz      .no_socket ;respond_seg_reset
161
        jz      .no_socket ;respond_seg_reset
162
 
162
 
163
        cmp     [ebx + SOCKET.Domain], AF_INET4
163
        cmp     [ebx + SOCKET.Domain], AF_INET4
164
        jne     .socket_loop
164
        jne     .socket_loop
165
 
165
 
166
        cmp     [ebx + SOCKET.Protocol], IP_PROTO_TCP
166
        cmp     [ebx + SOCKET.Protocol], IP_PROTO_TCP
167
        jne     .socket_loop
167
        jne     .socket_loop
168
 
168
 
169
        cmp     [ebx + TCP_SOCKET.LocalPort], si
169
        cmp     [ebx + TCP_SOCKET.LocalPort], si
170
        jne     .socket_loop
170
        jne     .socket_loop
171
 
171
 
172
        mov     eax, [ebx + IP_SOCKET.RemoteIP]
172
        mov     eax, [ebx + IP_SOCKET.RemoteIP]
173
        cmp     eax, [edi]                              ; Ipv4 source address
173
        cmp     eax, [edi + IPv4_header.SourceAddress]
174
        je      @f
174
        je      @f
175
        test    eax, eax
175
        test    eax, eax
176
        jnz     .socket_loop
176
        jnz     .socket_loop
177
       @@:
177
       @@:
178
 
178
 
179
        mov     ax, [ebx + TCP_SOCKET.RemotePort]
179
        mov     ax, [ebx + TCP_SOCKET.RemotePort]
180
        cmp     [edx + TCP_header.SourcePort], ax
180
        cmp     [edx + TCP_header.SourcePort], ax
181
        je      .found_socket
181
        je      .found_socket
182
        test    ax, ax
182
        test    ax, ax
183
        jnz     .socket_loop
183
        jnz     .socket_loop
184
  .found_socket:                                        ; ebx now contains the socketpointer
184
  .found_socket:                                        ; ebx now contains the socketpointer
185
        pusha
185
        pusha
186
        mov     ecx, socket_mutex
186
        mov     ecx, socket_mutex
187
        call    mutex_unlock
187
        call    mutex_unlock
188
        popa
188
        popa
189
 
189
 
190
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_input: socket ptr=%x state=%u flags=%x\n", ebx, [ebx + TCP_SOCKET.t_state], [edx + TCP_header.Flags]:2
190
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_input: socket ptr=%x state=%u flags=%x\n", ebx, [ebx + TCP_SOCKET.t_state], [edx + TCP_header.Flags]:2
191
 
191
 
192
;----------------------------
192
;----------------------------
193
; Check if socket isnt closed
193
; Check if socket isnt closed
194
 
194
 
195
        cmp     [ebx + TCP_SOCKET.t_state], TCPS_CLOSED
195
        cmp     [ebx + TCP_SOCKET.t_state], TCPS_CLOSED
196
        je      .drop_no_socket
196
        je      .drop_no_socket
197
 
197
 
198
;----------------
198
;----------------
199
; Lock the socket
199
; Lock the socket
200
 
200
 
201
        pusha
201
        pusha
202
        lea     ecx, [ebx + SOCKET.mutex]
202
        lea     ecx, [ebx + SOCKET.mutex]
203
        call    mutex_lock
203
        call    mutex_lock
204
        popa
204
        popa
205
 
205
 
206
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_input: socket locked\n"
206
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_input: socket locked\n"
207
 
207
 
208
;---------------------------
208
;---------------------------
209
; disable all temporary bits
209
; disable all temporary bits
210
 
210
 
211
        mov     [temp_bits], 0
211
        mov     [temp_bits], 0
212
 
212
 
213
;---------------------------------------
213
;---------------------------------------
214
; unscale the window into a 32 bit value
214
; unscale the window into a 32 bit value
215
 
215
 
216
        movzx   eax, [edx + TCP_header.Window]
216
        movzx   eax, [edx + TCP_header.Window]
217
        push    ecx
217
        push    ecx
218
        mov     cl, [ebx + TCP_SOCKET.SND_SCALE]
218
        mov     cl, [ebx + TCP_SOCKET.SND_SCALE]
219
        shl     eax, cl
219
        shl     eax, cl
220
        mov     dword [edx + TCP_header.Window], eax    ; word after window is checksum, we dont need checksum anymore
220
        mov     dword [edx + TCP_header.Window], eax    ; word after window is checksum, we dont need checksum anymore
221
        pop     ecx
221
        pop     ecx
222
 
222
 
223
;---------------------------------------
223
;---------------------------------------
224
; Are we accepting incoming connections?
224
; Are we accepting incoming connections?
225
 
225
 
226
        test    [ebx + SOCKET.options], SO_ACCEPTCON
226
        test    [ebx + SOCKET.options], SO_ACCEPTCON
227
        jz      .no_accept
227
        jz      .no_accept
228
 
228
 
229
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_input: Accepting new connection\n"
229
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_input: Accepting new connection\n"
230
 
230
 
231
        pusha
231
        pusha
232
        lea     ecx, [ebx + SOCKET.mutex]
232
        lea     ecx, [ebx + SOCKET.mutex]
233
        call    mutex_unlock
233
        call    mutex_unlock
234
        popa
234
        popa
235
 
235
 
236
        push    ecx edx esi edi         ;;;
236
        push    ecx edx esi edi
237
        call    SOCKET_fork
237
        call    SOCKET_fork
238
        pop     edi esi edx ecx
238
        pop     edi esi edx ecx
239
 
239
 
240
        test    eax, eax
240
        test    eax, eax
241
        jz      .drop_no_socket
241
        jz      .drop_no_socket
242
 
242
 
243
        mov     ebx, eax
243
        mov     ebx, eax
244
 
244
 
245
        mov     [temp_bits], TCP_BIT_DROPSOCKET
245
        mov     [temp_bits], TCP_BIT_DROPSOCKET
246
 
246
 
247
        push    dword [edi + 4]                         ; Ipv4 destination addres
247
        push    [edi + IPv4_header.DestinationAddress]
248
        pop     [ebx + IP_SOCKET.LocalIP]
248
        pop     [ebx + IP_SOCKET.LocalIP]
249
 
249
 
250
        push    [edx + TCP_header.DestinationPort]
250
        push    [edx + TCP_header.DestinationPort]
251
        pop     [ebx + TCP_SOCKET.LocalPort]
251
        pop     [ebx + TCP_SOCKET.LocalPort]
252
 
252
 
253
        mov     [ebx + TCP_SOCKET.t_state], TCPS_LISTEN
253
        mov     [ebx + TCP_SOCKET.t_state], TCPS_LISTEN
254
  .no_accept:
254
  .no_accept:
255
 
255
 
256
 
256
 
257
;-------------------------------------
257
;-------------------------------------
258
; Reset idle timer and keepalive timer
258
; Reset idle timer and keepalive timer
259
 
259
 
260
        mov     [ebx + TCP_SOCKET.t_idle], 0
260
        mov     [ebx + TCP_SOCKET.t_idle], 0
261
        mov     [ebx + TCP_SOCKET.timer_keepalive], TCP_time_keep_idle
261
        mov     [ebx + TCP_SOCKET.timer_keepalive], TCP_time_keep_idle
262
        or      [ebx + TCP_SOCKET.timer_flags], timer_flag_keepalive
262
        or      [ebx + TCP_SOCKET.timer_flags], timer_flag_keepalive
263
 
263
 
264
;--------------------
264
;--------------------
265
; Process TCP options
265
; Process TCP options
266
 
266
 
267
;;; FIXME: for LISTEN, options should be called after we determined route, we need it for MSS
267
;;; FIXME: for LISTEN, options should be called after we determined route, we need it for MSS
268
;;;        cmp     [ebx + TCP_SOCKET.t_state], TCPS_LISTEN ; no options when in listen state
268
;;;        cmp     [ebx + TCP_SOCKET.t_state], TCPS_LISTEN ; no options when in listen state
269
;;;        jz      .not_uni_xfer                           ; also no header prediction
269
;;;        jz      .not_uni_xfer                           ; also no header prediction
270
 
270
 
271
        push    ecx
271
        push    ecx
272
 
272
 
273
        mov     ecx, [dataoffset]
273
        mov     ecx, [dataoffset]
274
        cmp     ecx, sizeof.TCP_header                  ; Does header contain any options?
274
        cmp     ecx, sizeof.TCP_header                  ; Does header contain any options?
275
        je      .no_options
275
        je      .no_options
276
 
276
 
277
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_input: Segment has options\n"
277
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_input: Segment has options\n"
278
 
278
 
279
        add     ecx, edx
279
        add     ecx, edx
280
        lea     esi, [edx + sizeof.TCP_header]
280
        lea     esi, [edx + sizeof.TCP_header]
281
 
281
 
282
  .opt_loop:
282
  .opt_loop:
283
        cmp     esi, ecx                        ; are we scanning outside of header?
283
        cmp     esi, ecx                        ; are we scanning outside of header?
284
        jae     .no_options
284
        jae     .no_options
285
        lodsb
285
        lodsb
286
        cmp     al, TCP_OPT_EOL                 ; end of option list?
286
        cmp     al, TCP_OPT_EOL                 ; end of option list?
287
        je      .no_options
287
        je      .no_options
288
        cmp     al, TCP_OPT_NOP
288
        cmp     al, TCP_OPT_NOP
289
        je      .opt_loop
289
        je      .opt_loop
290
        cmp     al, TCP_OPT_MAXSEG
290
        cmp     al, TCP_OPT_MAXSEG
291
        je      .opt_maxseg
291
        je      .opt_maxseg
292
        cmp     al, TCP_OPT_WINDOW
292
        cmp     al, TCP_OPT_WINDOW
293
        je      .opt_window
293
        je      .opt_window
294
        cmp     al, TCP_OPT_SACK_PERMIT
294
        cmp     al, TCP_OPT_SACK_PERMIT
295
        je      .opt_sack_permit
295
        je      .opt_sack_permit
296
;        cmp     al, TCP_OPT_SACK
296
;        cmp     al, TCP_OPT_SACK
297
;        je      .opt_sack
297
;        je      .opt_sack
298
        cmp     al, TCP_OPT_TIMESTAMP
298
        cmp     al, TCP_OPT_TIMESTAMP
299
        je      .opt_timestamp
299
        je      .opt_timestamp
300
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_input: unknown option:%u\n", al
300
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_input: unknown option:%u\n", al
301
        jmp     .no_options                     ; If we reach here, some unknown options were received, skip them all!
301
        jmp     .no_options                     ; If we reach here, some unknown options were received, skip them all!
302
 
302
 
303
  .opt_maxseg:
303
  .opt_maxseg:
304
        lodsb
304
        lodsb
305
        cmp     al, 4
305
        cmp     al, 4
306
        jne     .no_options                     ; error occured, ignore all options!
306
        jne     .no_options                     ; error occured, ignore all options!
307
 
307
 
308
        test    [edx + TCP_header.Flags], TH_SYN
308
        test    [edx + TCP_header.Flags], TH_SYN
309
        jz      @f
309
        jz      @f
310
 
310
 
311
        xor     eax, eax
311
        xor     eax, eax
312
        lodsw
312
        lodsw
313
        rol     ax, 8
313
        rol     ax, 8
314
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_input: Maxseg=%u\n", eax
314
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_input: Maxseg=%u\n", eax
315
        call    TCP_mss
315
        call    TCP_mss
316
       @@:
316
       @@:
317
        jmp     .opt_loop
317
        jmp     .opt_loop
318
 
318
 
319
 
319
 
320
  .opt_window:
320
  .opt_window:
321
        lodsb
321
        lodsb
322
        cmp     al, 3
322
        cmp     al, 3
323
        jne     .no_options
323
        jne     .no_options
324
 
324
 
325
        test    [edx + TCP_header.Flags], TH_SYN
325
        test    [edx + TCP_header.Flags], TH_SYN
326
        jz      @f
326
        jz      @f
327
 
327
 
328
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_input: Got window scale option\n"
328
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_input: Got window scale option\n"
329
        or      [ebx + TCP_SOCKET.t_flags], TF_RCVD_SCALE
329
        or      [ebx + TCP_SOCKET.t_flags], TF_RCVD_SCALE
330
 
330
 
331
        lodsb
331
        lodsb
332
        mov     [ebx + TCP_SOCKET.SND_SCALE], al
332
        mov     [ebx + TCP_SOCKET.SND_SCALE], al
333
        ;;;;; TODO
333
        ;;;;; TODO
334
 
334
 
335
       @@:
335
       @@:
336
        jmp     .opt_loop
336
        jmp     .opt_loop
337
 
337
 
338
 
338
 
339
  .opt_sack_permit:
339
  .opt_sack_permit:
340
        lodsb
340
        lodsb
341
        cmp     al, 2
341
        cmp     al, 2
342
        jne     .no_options
342
        jne     .no_options
343
 
343
 
344
        test    [edx + TCP_header.Flags], TH_SYN
344
        test    [edx + TCP_header.Flags], TH_SYN
345
        jz      @f
345
        jz      @f
346
 
346
 
347
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_input: Selective Acknowledgement permitted\n"
347
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_input: Selective Acknowledgement permitted\n"
348
        or      [ebx + TCP_SOCKET.t_flags], TF_SACK_PERMIT
348
        or      [ebx + TCP_SOCKET.t_flags], TF_SACK_PERMIT
349
 
349
 
350
       @@:
350
       @@:
351
        jmp     .opt_loop
351
        jmp     .opt_loop
352
 
352
 
353
 
353
 
354
  .opt_timestamp:
354
  .opt_timestamp:
355
        lodsb
355
        lodsb
356
        cmp     al, 10                          ; length must be 10
356
        cmp     al, 10                          ; length must be 10
357
        jne     .no_options
357
        jne     .no_options
358
 
358
 
359
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_input: Got timestamp option\n"
359
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_input: Got timestamp option\n"
360
 
360
 
361
        test    [edx + TCP_header.Flags], TH_SYN
361
        test    [edx + TCP_header.Flags], TH_SYN
362
        jz      @f
362
        jz      @f
363
        or      [ebx + TCP_SOCKET.t_flags], TF_RCVD_TSTMP
363
        or      [ebx + TCP_SOCKET.t_flags], TF_RCVD_TSTMP
364
       @@:
364
       @@:
365
 
365
 
366
        lodsd
366
        lodsd
367
        bswap   eax
367
        bswap   eax
368
        mov     [ebx + TCP_SOCKET.ts_val], eax
368
        mov     [ebx + TCP_SOCKET.ts_val], eax
369
        lodsd                                   ; timestamp echo reply
369
        lodsd                                   ; timestamp echo reply
370
        mov     [ebx + TCP_SOCKET.ts_ecr], eax
370
        mov     [ebx + TCP_SOCKET.ts_ecr], eax
371
        or      [temp_bits], TCP_BIT_TIMESTAMP
371
        or      [temp_bits], TCP_BIT_TIMESTAMP
372
 
372
 
373
        ; Since we have a timestamp, lets do the paws test right away!
373
        ; Since we have a timestamp, lets do the paws test right away!
374
 
374
 
375
        test    [edx + TCP_header.Flags], TH_RST
375
        test    [edx + TCP_header.Flags], TH_RST
376
        jnz     .no_paws
376
        jnz     .no_paws
377
 
377
 
378
        mov     eax, [ebx + TCP_SOCKET.ts_recent]
378
        mov     eax, [ebx + TCP_SOCKET.ts_recent]
379
        test    eax, eax
379
        test    eax, eax
380
        jz      .no_paws
380
        jz      .no_paws
381
        cmp     eax, [ebx + TCP_SOCKET.ts_val]
381
        cmp     eax, [ebx + TCP_SOCKET.ts_val]
382
        jbe     .no_paws
382
        jbe     .no_paws
383
 
383
 
384
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_input: PAWS: detected an old segment\n"
384
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_input: PAWS: detected an old segment\n"
385
 
385
 
386
        mov     eax, [timestamp]
386
        mov     eax, [timestamp]
387
        sub     eax, [ebx + TCP_SOCKET.ts_recent_age]
387
        sub     eax, [ebx + TCP_SOCKET.ts_recent_age]
388
 
388
 
389
        pop     ecx
389
        pop     ecx
390
        cmp     eax, TCP_PAWS_IDLE
390
        cmp     eax, TCP_PAWS_IDLE
391
        jle     .paws_drop
391
        jle     .paws_drop
392
        push    ecx
392
        push    ecx
393
        mov     [ebx + TCP_SOCKET.ts_recent], 0         ; timestamp was invalid, fix it.
393
        mov     [ebx + TCP_SOCKET.ts_recent], 0         ; timestamp was invalid, fix it.
394
  .no_paws:
394
  .no_paws:
395
        jmp     .opt_loop
395
        jmp     .opt_loop
396
 
396
 
397
  .paws_drop:
397
  .paws_drop:
398
        inc     [TCPS_rcvduppack]                       ; update stats
398
        inc     [TCPS_rcvduppack]                       ; update stats
399
        add     [TCPS_rcvdupbyte], ecx
399
        add     [TCPS_rcvdupbyte], ecx
400
        inc     [TCPS_pawsdrop]
400
        inc     [TCPS_pawsdrop]
401
        jmp     .drop_after_ack
401
        jmp     .drop_after_ack
402
 
402
 
403
  .no_options:
403
  .no_options:
404
 
404
 
405
        pop     ecx
405
        pop     ecx
406
 
406
 
407
;-----------------------------------------------------------------------
407
;-----------------------------------------------------------------------
408
; Time to do some header prediction (Original Principle by Van Jacobson)
408
; Time to do some header prediction (Original Principle by Van Jacobson)
409
 
409
 
410
; There are two common cases for an uni-directional data transfer.
410
; There are two common cases for an uni-directional data transfer.
411
;
411
;
412
; General rule: the packets has no control flags, is in-sequence,
412
; General rule: the packets has no control flags, is in-sequence,
413
;   window width didnt change and we're not retransmitting.
413
;   window width didnt change and we're not retransmitting.
414
;
414
;
415
; Second rules:
415
; Second rules:
416
;  -  If the length is 0 and the ACK moved forward, we're the sender side of the transfer.
416
;  -  If the length is 0 and the ACK moved forward, we're the sender side of the transfer.
417
;      In this case we'll free the ACK'ed data and notify higher levels that we have free space in buffer
417
;      In this case we'll free the ACK'ed data and notify higher levels that we have free space in buffer
418
;
418
;
419
;  -  If the length is not 0 and the ACK didn't move, we're the receiver side of the transfer.
419
;  -  If the length is not 0 and the ACK didn't move, we're the receiver side of the transfer.
420
;      If the packets are in order (data queue is empty), add the data to the socket buffer and request a delayed ACK
420
;      If the packets are in order (data queue is empty), add the data to the socket buffer and request a delayed ACK
421
 
421
 
422
        cmp     [ebx + TCP_SOCKET.t_state], TCPS_ESTABLISHED
422
        cmp     [ebx + TCP_SOCKET.t_state], TCPS_ESTABLISHED
423
        jnz     .not_uni_xfer
423
        jnz     .not_uni_xfer
424
 
424
 
425
        test    [edx + TCP_header.Flags], TH_SYN + TH_FIN + TH_RST + TH_URG
425
        test    [edx + TCP_header.Flags], TH_SYN + TH_FIN + TH_RST + TH_URG
426
        jnz     .not_uni_xfer
426
        jnz     .not_uni_xfer
427
 
427
 
428
        test    [edx + TCP_header.Flags], TH_ACK
428
        test    [edx + TCP_header.Flags], TH_ACK
429
        jz      .not_uni_xfer
429
        jz      .not_uni_xfer
430
 
430
 
431
        mov     eax, [edx + TCP_header.SequenceNumber]
431
        mov     eax, [edx + TCP_header.SequenceNumber]
432
        cmp     eax, [ebx + TCP_SOCKET.RCV_NXT]
432
        cmp     eax, [ebx + TCP_SOCKET.RCV_NXT]
433
        jne     .not_uni_xfer
433
        jne     .not_uni_xfer
434
 
434
 
435
        mov     eax, dword [edx + TCP_header.Window]
435
        mov     eax, dword [edx + TCP_header.Window]
436
        cmp     eax, [ebx + TCP_SOCKET.SND_WND]
436
        cmp     eax, [ebx + TCP_SOCKET.SND_WND]
437
        jne     .not_uni_xfer
437
        jne     .not_uni_xfer
438
 
438
 
439
        mov     eax, [ebx + TCP_SOCKET.SND_NXT]
439
        mov     eax, [ebx + TCP_SOCKET.SND_NXT]
440
        cmp     eax, [ebx + TCP_SOCKET.SND_MAX]
440
        cmp     eax, [ebx + TCP_SOCKET.SND_MAX]
441
        jne     .not_uni_xfer
441
        jne     .not_uni_xfer
442
 
442
 
443
;---------------------------------------
443
;---------------------------------------
444
; check if we are sender in the uni-xfer
444
; check if we are sender in the uni-xfer
445
 
445
 
446
; If the following 4 conditions are all true, this segment is a pure ACK.
446
; If the following 4 conditions are all true, this segment is a pure ACK.
447
;
447
;
448
; - The segment contains no data.
448
; - The segment contains no data.
449
        test    ecx, ecx
449
        test    ecx, ecx
450
        jnz     .not_sender
450
        jnz     .not_sender
451
 
451
 
452
; - The congestion window is greater than or equal to the current send window.
452
; - The congestion window is greater than or equal to the current send window.
453
;     This test is true only if the window is fully open, that is, the connection is not in the middle of slow start or congestion avoidance.
453
;     This test is true only if the window is fully open, that is, the connection is not in the middle of slow start or congestion avoidance.
454
        mov     eax, [ebx + TCP_SOCKET.SND_CWND]
454
        mov     eax, [ebx + TCP_SOCKET.SND_CWND]
455
        cmp     eax, [ebx + TCP_SOCKET.SND_WND]
455
        cmp     eax, [ebx + TCP_SOCKET.SND_WND]
456
        jb      .not_uni_xfer
456
        jb      .not_uni_xfer
457
 
457
 
458
; - The acknowledgment field in the segment is less than or equal to the maximum sequence number sent.
458
; - The acknowledgment field in the segment is less than or equal to the maximum sequence number sent.
459
        mov     eax, [edx + TCP_header.AckNumber]
459
        mov     eax, [edx + TCP_header.AckNumber]
460
        cmp     eax, [ebx + TCP_SOCKET.SND_MAX]
460
        cmp     eax, [ebx + TCP_SOCKET.SND_MAX]
461
        ja      .not_uni_xfer
461
        ja      .not_uni_xfer
462
 
462
 
463
; - The acknowledgment field in the segment is greater than the largest unacknowledged sequence number.
463
; - The acknowledgment field in the segment is greater than the largest unacknowledged sequence number.
464
        sub     eax, [ebx + TCP_SOCKET.SND_UNA]
464
        sub     eax, [ebx + TCP_SOCKET.SND_UNA]
465
        jbe     .not_uni_xfer
465
        jbe     .not_uni_xfer
466
 
466
 
467
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_input: Header prediction: we are sender\n"
467
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_input: Header prediction: we are sender\n"
468
 
468
 
469
;---------------------------------
469
;---------------------------------
470
; Packet is a pure ACK, process it
470
; Packet is a pure ACK, process it
471
 
471
 
472
; Delete acknowledged bytes from send buffer
472
; Delete acknowledged bytes from send buffer
473
        pusha
473
        pusha
474
        mov     ecx, eax
474
        mov     ecx, eax
475
        lea     eax, [ebx + STREAM_SOCKET.snd]
475
        lea     eax, [ebx + STREAM_SOCKET.snd]
476
        call    SOCKET_ring_free
476
        call    SOCKET_ring_free
477
        popa
477
        popa
478
 
478
 
479
; Update RTT estimators
479
; Update RTT estimators
480
 
480
 
481
        test    [temp_bits], TCP_BIT_TIMESTAMP
481
        test    [temp_bits], TCP_BIT_TIMESTAMP
482
        jz      .no_timestamp_rtt
482
        jz      .no_timestamp_rtt
483
        mov     eax, [timestamp]
483
        mov     eax, [timestamp]
484
        sub     eax, [ebx + TCP_SOCKET.ts_ecr]
484
        sub     eax, [ebx + TCP_SOCKET.ts_ecr]
485
        inc     eax
485
        inc     eax
486
        call    TCP_xmit_timer
486
        call    TCP_xmit_timer
487
        jmp     .rtt_done
487
        jmp     .rtt_done
488
 
-
 
489
  .no_timestamp_rtt:
488
  .no_timestamp_rtt:
-
 
489
 
490
        cmp     [ebx + TCP_SOCKET.t_rtt], 0
490
        cmp     [ebx + TCP_SOCKET.t_rtt], 0
491
        je      .rtt_done
491
        je      .rtt_done
492
        mov     eax, [edx + TCP_header.AckNumber]
492
        mov     eax, [edx + TCP_header.AckNumber]
493
        cmp     eax, [ebx + TCP_SOCKET.t_rtseq]
493
        cmp     eax, [ebx + TCP_SOCKET.t_rtseq]
494
        jbe     .rtt_done
494
        jbe     .rtt_done
495
        mov     eax, [ebx + TCP_SOCKET.t_rtt]
495
        mov     eax, [ebx + TCP_SOCKET.t_rtt]
496
        call    TCP_xmit_timer
496
        call    TCP_xmit_timer
497
 
-
 
498
  .rtt_done:
497
  .rtt_done:
499
 
498
 
500
; update window pointers
499
; update window pointers
501
        mov     eax, [edx + TCP_header.AckNumber]
500
        mov     eax, [edx + TCP_header.AckNumber]
502
        mov     [ebx + TCP_SOCKET.SND_UNA], eax
501
        mov     [ebx + TCP_SOCKET.SND_UNA], eax
503
 
502
 
504
; Stop retransmit timer
503
; Stop retransmit timer
505
        and     [ebx + TCP_SOCKET.timer_flags], not timer_flag_retransmission
504
        and     [ebx + TCP_SOCKET.timer_flags], not timer_flag_retransmission
506
 
505
 
507
; Unlock the socket
506
; Unlock the socket
508
        pusha
507
        pusha
509
        lea     ecx, [ebx + SOCKET.mutex]
508
        lea     ecx, [ebx + SOCKET.mutex]
510
        call    mutex_unlock
509
        call    mutex_unlock
511
        popa
510
        popa
512
 
511
 
513
; Awaken waiting processes
512
; Awaken waiting processes
514
        mov     eax, ebx
513
        mov     eax, ebx
515
        call    SOCKET_notify
514
        call    SOCKET_notify
516
 
515
 
517
; Generate more output
516
; Generate more output
518
        call    TCP_output
517
        call    TCP_output
519
 
518
 
520
        jmp     .drop_no_socket
519
        jmp     .drop_no_socket
521
 
520
 
522
;-------------------------------------------------
521
;-------------------------------------------------
523
; maybe we are the receiver in the uni-xfer then..
522
; maybe we are the receiver in the uni-xfer then..
524
 
523
 
525
  .not_sender:
524
  .not_sender:
526
; - The amount of data in the segment is greater than 0 (data count is in ecx)
525
; - The amount of data in the segment is greater than 0 (data count is in ecx)
527
 
526
 
528
; - The acknowledgment field equals the largest unacknowledged sequence number. This means no data is acknowledged by this segment.
527
; - The acknowledgment field equals the largest unacknowledged sequence number. This means no data is acknowledged by this segment.
529
        mov     eax, [edx + TCP_header.AckNumber]
528
        mov     eax, [edx + TCP_header.AckNumber]
530
        cmp     eax, [ebx + TCP_SOCKET.SND_UNA]
529
        cmp     eax, [ebx + TCP_SOCKET.SND_UNA]
531
        jne     .not_uni_xfer
530
        jne     .not_uni_xfer
532
 
531
 
533
; - The reassembly list of out-of-order segments for the connection is empty.
532
; - The reassembly list of out-of-order segments for the connection is empty.
534
        cmp     [ebx + TCP_SOCKET.seg_next], 0
533
        cmp     [ebx + TCP_SOCKET.seg_next], 0
535
        jne     .not_uni_xfer
534
        jne     .not_uni_xfer
536
 
535
 
537
; Complete processing of received data
536
; Complete processing of received data
538
 
537
 
539
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_input: Header prediction: we are receiving %u bytes\n", ecx
538
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_input: Header prediction: we are receiving %u bytes\n", ecx
540
 
539
 
541
        mov     esi, [dataoffset]
540
        mov     esi, [dataoffset]
542
        add     esi, edx
541
        add     esi, edx
543
        lea     eax, [ebx + STREAM_SOCKET.rcv]
542
        lea     eax, [ebx + STREAM_SOCKET.rcv]
544
        call    SOCKET_ring_write                       ; Add the data to the socket buffer
543
        call    SOCKET_ring_write                       ; Add the data to the socket buffer
545
        add     [ebx + TCP_SOCKET.RCV_NXT], ecx         ; Update sequence number with number of bytes we have copied
544
        add     [ebx + TCP_SOCKET.RCV_NXT], ecx         ; Update sequence number with number of bytes we have copied
546
 
545
 
547
        mov     eax, ebx
546
        mov     eax, ebx
548
        call    SOCKET_notify
547
        call    SOCKET_notify
549
 
548
 
550
        or      [ebx + TCP_SOCKET.t_flags], TF_DELACK   ; Set delayed ack flag
549
        or      [ebx + TCP_SOCKET.t_flags], TF_DELACK   ; Set delayed ack flag
551
 
550
 
552
        jmp     .drop
551
        jmp     .drop
553
 
552
 
554
;--------------------------------------------------
553
;--------------------------------------------------
555
; Header prediction failed, do it the slow way
554
; Header prediction failed, do it the slow way
556
 
555
 
557
  .not_uni_xfer:
556
  .not_uni_xfer:
558
 
557
 
559
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_input: Header prediction failed\n"
558
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_input: Header prediction failed\n"
560
 
559
 
561
; Calculate receive window size
560
; Calculate receive window size
562
        push    edx
561
        push    edx
563
        mov     eax, SOCKET_MAXDATA
562
        mov     eax, SOCKET_MAXDATA
564
        sub     eax, [ebx + STREAM_SOCKET.rcv.size]
563
        sub     eax, [ebx + STREAM_SOCKET.rcv.size]
565
        DEBUGF  DEBUG_NETWORK_VERBOSE, "Space in receive buffer=%d\n", eax
564
        DEBUGF  DEBUG_NETWORK_VERBOSE, "Space in receive buffer=%d\n", eax
566
        mov     edx, [ebx + TCP_SOCKET.RCV_ADV]
565
        mov     edx, [ebx + TCP_SOCKET.RCV_ADV]
567
        sub     edx, [ebx + TCP_SOCKET.RCV_NXT]
566
        sub     edx, [ebx + TCP_SOCKET.RCV_NXT]
568
        DEBUGF  DEBUG_NETWORK_VERBOSE, "Current advertised window=%d\n", edx
567
        DEBUGF  DEBUG_NETWORK_VERBOSE, "Current advertised window=%d\n", edx
569
        cmp     eax, edx
568
        cmp     eax, edx
570
        jg      @f
569
        jg      @f
571
        mov     eax, edx
570
        mov     eax, edx
572
       @@:
571
       @@:
573
        DEBUGF  DEBUG_NETWORK_VERBOSE, "Receive window size=%d\n", eax
572
        DEBUGF  DEBUG_NETWORK_VERBOSE, "Receive window size=%d\n", eax
574
        mov     [ebx + TCP_SOCKET.RCV_WND], eax
573
        mov     [ebx + TCP_SOCKET.RCV_WND], eax
575
        pop     edx
574
        pop     edx
576
 
575
 
577
; If we are in listen or syn_sent state, go to that specific code right away
576
; If we are in listen or syn_sent state, go to that specific code right away
578
 
577
 
579
        cmp     [ebx + TCP_SOCKET.t_state], TCPS_LISTEN
578
        cmp     [ebx + TCP_SOCKET.t_state], TCPS_LISTEN
580
        je      .LISTEN
579
        je      .LISTEN
581
 
580
 
582
        cmp     [ebx + TCP_SOCKET.t_state], TCPS_SYN_SENT
581
        cmp     [ebx + TCP_SOCKET.t_state], TCPS_SYN_SENT
583
        je      .SYN_SENT
582
        je      .SYN_SENT
584
 
583
 
585
;----------------------------
584
;----------------------------
586
; trim any data not in window
585
; trim any data not in window
587
 
586
 
588
; 1. Check for duplicate data at beginning of segment
587
; 1. Check for duplicate data at beginning of segment
589
 
588
 
590
; Calculate number of bytes we need to drop
589
; Calculate number of bytes we need to drop
591
        mov     eax, [ebx + TCP_SOCKET.RCV_NXT]
590
        mov     eax, [ebx + TCP_SOCKET.RCV_NXT]
592
        sub     eax, [edx + TCP_header.SequenceNumber]
591
        sub     eax, [edx + TCP_header.SequenceNumber]
593
        jle     .no_duplicate
592
        jle     .no_duplicate
594
 
593
 
595
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_input: %u bytes duplicate data!\n", eax
594
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_input: %u bytes duplicate data!\n", eax
596
 
595
 
597
        test    [edx + TCP_header.Flags], TH_SYN
596
        test    [edx + TCP_header.Flags], TH_SYN
598
        jz      .no_dup_syn
597
        jz      .no_dup_syn
599
 
598
 
600
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_input: got duplicate syn\n"
599
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_input: got duplicate syn\n"
601
 
600
 
602
        and     [edx + TCP_header.Flags], not (TH_SYN)
601
        and     [edx + TCP_header.Flags], not (TH_SYN)
603
        inc     [edx + TCP_header.SequenceNumber]
602
        inc     [edx + TCP_header.SequenceNumber]
604
 
603
 
605
        cmp     [edx + TCP_header.UrgentPointer], 1
604
        cmp     [edx + TCP_header.UrgentPointer], 1
606
        jbe     @f
605
        jbe     @f
607
        dec     [edx + TCP_header.UrgentPointer]
606
        dec     [edx + TCP_header.UrgentPointer]
608
        jmp     .dup_syn
607
        jmp     .dup_syn
609
       @@:
608
       @@:
610
        and     [edx + TCP_header.Flags], not (TH_URG)
609
        and     [edx + TCP_header.Flags], not (TH_URG)
611
  .dup_syn:
610
  .dup_syn:
612
        dec     eax
611
        dec     eax
613
  .no_dup_syn:
612
  .no_dup_syn:
614
 
613
 
615
; 2. Check for entire duplicate segment
614
; 2. Check for entire duplicate segment
616
        cmp     eax, ecx                ; eax holds number of bytes to drop, ecx is data size
615
        cmp     eax, ecx                ; eax holds number of bytes to drop, ecx is data size
617
        jb      .duplicate
616
        jb      .duplicate
618
        jnz     @f
617
        jnz     @f
619
        test    [edx + TCP_header.Flags], TH_FIN
618
        test    [edx + TCP_header.Flags], TH_FIN
620
        jnz     .duplicate
619
        jnz     .duplicate
621
       @@:
620
       @@:
622
 
621
 
623
; Any valid FIN must be to the left of the window.
622
; Any valid FIN must be to the left of the window.
624
; At this point the FIN must be out of sequence or a duplicate, drop it
623
; At this point the FIN must be out of sequence or a duplicate, drop it
625
        and     [edx + TCP_header.Flags], not TH_FIN
624
        and     [edx + TCP_header.Flags], not TH_FIN
626
 
625
 
627
; send an ACK and resynchronize and drop any data.
626
; send an ACK and resynchronize and drop any data.
628
; But keep on processing for RST or ACK
627
; But keep on processing for RST or ACK
629
        or      [ebx + TCP_SOCKET.t_flags], TF_ACKNOW
628
        or      [ebx + TCP_SOCKET.t_flags], TF_ACKNOW
630
        mov     eax, ecx
629
        mov     eax, ecx
631
 
630
 
632
        inc     [TCPS_rcvpartduppack]
631
        inc     [TCPS_rcvpartduppack]
633
 
632
 
634
;;; TODO: update stats
633
;;; TODO: update stats
635
 
634
 
636
;-----------------------------------------------
635
;-----------------------------------------------
637
; Remove duplicate data and update urgent offset
636
; Remove duplicate data and update urgent offset
638
 
637
 
639
  .duplicate:
638
  .duplicate:
640
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_input: trimming duplicate data\n"
639
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_input: trimming duplicate data\n"
641
 
640
 
642
; Trim data from left side of window
641
; Trim data from left side of window
643
        add     [dataoffset], eax
642
        add     [dataoffset], eax
644
        add     [edx + TCP_header.SequenceNumber], eax
643
        add     [edx + TCP_header.SequenceNumber], eax
645
        sub     ecx, eax
644
        sub     ecx, eax
646
 
645
 
647
        sub     [edx + TCP_header.UrgentPointer], ax
646
        sub     [edx + TCP_header.UrgentPointer], ax
648
        jg      @f
647
        jg      @f
649
        and     [edx + TCP_header.Flags], not (TH_URG)
648
        and     [edx + TCP_header.Flags], not (TH_URG)
650
        mov     [edx + TCP_header.UrgentPointer], 0
649
        mov     [edx + TCP_header.UrgentPointer], 0
651
       @@:
650
       @@:
652
 
651
 
653
;--------------------------------------------------
652
;--------------------------------------------------
654
; Handle data that arrives after process terminates
653
; Handle data that arrives after process terminates
655
 
654
 
656
  .no_duplicate:
655
  .no_duplicate:
657
        cmp     [ebx + SOCKET.PID], 0                   ;;; TODO: use socket flags instead??
656
        cmp     [ebx + SOCKET.PID], 0                   ;;; TODO: use socket flags instead??
658
        jne     .not_terminated
657
        jne     .not_terminated
659
        cmp     [ebx + TCP_SOCKET.t_state], TCPS_CLOSE_WAIT
658
        cmp     [ebx + TCP_SOCKET.t_state], TCPS_CLOSE_WAIT
660
        jbe     .not_terminated
659
        jbe     .not_terminated
661
        test    ecx, ecx
660
        test    ecx, ecx
662
        jz      .not_terminated
661
        jz      .not_terminated
663
 
662
 
664
        mov     eax, ebx
663
        mov     eax, ebx
665
        call    TCP_close
664
        call    TCP_close
666
        inc     [TCPS_rcvafterclose]
665
        inc     [TCPS_rcvafterclose]
667
        jmp     .respond_seg_reset
666
        jmp     .respond_seg_reset
668
 
667
 
669
;----------------------------------------
668
;----------------------------------------
670
; Remove data beyond right edge of window
669
; Remove data beyond right edge of window
671
 
670
 
672
  .not_terminated:
671
  .not_terminated:
673
        mov     eax, [edx + TCP_header.SequenceNumber]
672
        mov     eax, [edx + TCP_header.SequenceNumber]
674
        add     eax, ecx
673
        add     eax, ecx
675
        sub     eax, [ebx + TCP_SOCKET.RCV_NXT]
674
        sub     eax, [ebx + TCP_SOCKET.RCV_NXT]
676
        sub     eax, [ebx + TCP_SOCKET.RCV_WND]         ; eax now holds the number of bytes to drop
675
        sub     eax, [ebx + TCP_SOCKET.RCV_WND]         ; eax now holds the number of bytes to drop
677
        jle     .no_excess_data
676
        jle     .no_excess_data
678
 
677
 
679
        DEBUGF  DEBUG_NETWORK_VERBOSE, "%d bytes beyond right edge of window\n", eax
678
        DEBUGF  DEBUG_NETWORK_VERBOSE, "%d bytes beyond right edge of window\n", eax
680
 
679
 
681
;;; TODO: update stats
680
;;; TODO: update stats
682
        cmp     eax, ecx
681
        cmp     eax, ecx
683
        jl      .dont_drop_all
682
        jl      .dont_drop_all
684
; If a new connection request is received while in TIME_WAIT, drop the old connection and start over,
683
; If a new connection request is received while in TIME_WAIT, drop the old connection and start over,
685
; if the sequence numbers are above the previous ones
684
; if the sequence numbers are above the previous ones
686
 
685
 
687
        test    [edx + TCP_header.Flags], TH_SYN
686
        test    [edx + TCP_header.Flags], TH_SYN
688
        jz      .no_new_request
687
        jz      .no_new_request
689
        cmp     [ebx + TCP_SOCKET.t_state], TCPS_TIMED_WAIT
688
        cmp     [ebx + TCP_SOCKET.t_state], TCPS_TIMED_WAIT
690
        jne     .no_new_request
689
        jne     .no_new_request
691
;        mov     edx, [ebx + TCP_SOCKET.RCV_NXT]
690
;        mov     edx, [ebx + TCP_SOCKET.RCV_NXT]
692
;        cmp     edx, [edx + TCP_header.SequenceNumber]
691
;        cmp     edx, [edx + TCP_header.SequenceNumber]
693
;        add     edx, 64000      ; TCP_ISSINCR   FIXME
692
;        add     edx, 64000      ; TCP_ISSINCR   FIXME
694
        mov     eax, ebx
693
        mov     eax, ebx
695
        call    TCP_close
694
        call    TCP_close
696
        jmp     .findpcb        ; FIXME: skip code for unscaling window, ...
695
        jmp     .findpcb        ; FIXME: skip code for unscaling window, ...
697
  .no_new_request:
696
  .no_new_request:
698
 
697
 
699
; If window is closed, we can only take segments at window edge, and have to drop data and PUSH from
698
; If window is closed, we can only take segments at window edge, and have to drop data and PUSH from
700
; incoming segments. Continue processing, but remember to ACK. Otherwise drop segment and ACK
699
; incoming segments. Continue processing, but remember to ACK. Otherwise drop segment and ACK
701
 
700
 
702
        cmp     [ebx + TCP_SOCKET.RCV_WND], 0
701
        cmp     [ebx + TCP_SOCKET.RCV_WND], 0
703
        jne     .drop_after_ack
702
        jne     .drop_after_ack
704
        mov     esi, [edx + TCP_header.SequenceNumber]
703
        mov     esi, [edx + TCP_header.SequenceNumber]
705
        cmp     esi, [ebx + TCP_SOCKET.RCV_NXT]
704
        cmp     esi, [ebx + TCP_SOCKET.RCV_NXT]
706
        jne     .drop_after_ack
705
        jne     .drop_after_ack
707
 
706
 
708
        or      [ebx + TCP_SOCKET.t_flags], TF_ACKNOW
707
        or      [ebx + TCP_SOCKET.t_flags], TF_ACKNOW
709
;;; TODO: update stats
708
;;; TODO: update stats
710
  .dont_drop_all:
709
  .dont_drop_all:
711
;;; TODO: update stats
710
;;; TODO: update stats
712
        DEBUGF  DEBUG_NETWORK_VERBOSE, "Trimming %u bytes from the right of the window\n"
711
        DEBUGF  DEBUG_NETWORK_VERBOSE, "Trimming %u bytes from the right of the window\n"
713
        sub     ecx, eax        ; remove data from the right side of window (decrease data length)
712
        sub     ecx, eax        ; remove data from the right side of window (decrease data length)
714
        and     [edx + TCP_header.Flags], not (TH_PUSH or TH_FIN)
713
        and     [edx + TCP_header.Flags], not (TH_PUSH or TH_FIN)
715
  .no_excess_data:
714
  .no_excess_data:
716
 
715
 
717
;-----------------
716
;-----------------
718
; Record timestamp
717
; Record timestamp
719
 
718
 
720
; If last ACK falls within this segments sequence numbers, record its timestamp
719
; If last ACK falls within this segments sequence numbers, record its timestamp
721
        test    [temp_bits], TCP_BIT_TIMESTAMP
720
        test    [temp_bits], TCP_BIT_TIMESTAMP
722
        jz      .no_timestamp
721
        jz      .no_timestamp
723
        mov     eax, [ebx + TCP_SOCKET.last_ack_sent]
722
        mov     eax, [ebx + TCP_SOCKET.last_ack_sent]
724
        sub     eax, [edx + TCP_header.SequenceNumber]
723
        sub     eax, [edx + TCP_header.SequenceNumber]
725
        jb      .no_timestamp
724
        jb      .no_timestamp
726
        test    [ebx + TCP_header.Flags], TH_SYN or TH_FIN      ; syn and fin occupy one byte
725
        test    [ebx + TCP_header.Flags], TH_SYN or TH_FIN      ; syn and fin occupy one byte
727
        jz      @f
726
        jz      @f
728
        dec     eax
727
        dec     eax
729
       @@:
728
       @@:
730
        sub     eax, ecx
729
        sub     eax, ecx
731
        jae     .no_timestamp
730
        jae     .no_timestamp
732
 
731
 
733
        DEBUGF  DEBUG_NETWORK_VERBOSE, "Recording timestamp\n"
732
        DEBUGF  DEBUG_NETWORK_VERBOSE, "Recording timestamp\n"
734
 
733
 
735
        mov     eax, [timestamp]
734
        mov     eax, [timestamp]
736
        mov     [ebx + TCP_SOCKET.ts_recent_age], eax
735
        mov     [ebx + TCP_SOCKET.ts_recent_age], eax
737
        mov     eax, [ebx + TCP_SOCKET.ts_val]
736
        mov     eax, [ebx + TCP_SOCKET.ts_val]
738
        mov     [ebx + TCP_SOCKET.ts_recent], eax
737
        mov     [ebx + TCP_SOCKET.ts_recent], eax
739
  .no_timestamp:
738
  .no_timestamp:
740
 
739
 
741
;------------------
740
;------------------
742
; Process RST flags
741
; Process RST flags
743
 
742
 
744
        test    [edx + TCP_header.Flags], TH_RST
743
        test    [edx + TCP_header.Flags], TH_RST
745
        jz      .no_rst
744
        jz      .no_rst
746
 
745
 
747
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_input: Got an RST flag\n"
746
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_input: Got an RST flag\n"
748
 
747
 
749
        mov     eax, [ebx + TCP_SOCKET.t_state]
748
        mov     eax, [ebx + TCP_SOCKET.t_state]
750
        shl     eax, 2
749
        shl     eax, 2
751
        jmp     dword [eax + .rst_sw_list]
750
        jmp     dword [eax + .rst_sw_list]
752
 
751
 
753
  .rst_sw_list:
752
  .rst_sw_list:
754
        dd      .no_rst         ; TCPS_CLOSED
753
        dd      .no_rst         ; TCPS_CLOSED
755
        dd      .no_rst         ; TCPS_LISTEN
754
        dd      .no_rst         ; TCPS_LISTEN
756
        dd      .no_rst         ; TCPS_SYN_SENT
755
        dd      .no_rst         ; TCPS_SYN_SENT
757
        dd      .econnrefused   ; TCPS_SYN_RECEIVED
756
        dd      .econnrefused   ; TCPS_SYN_RECEIVED
758
        dd      .econnreset     ; TCPS_ESTABLISHED
757
        dd      .econnreset     ; TCPS_ESTABLISHED
759
        dd      .econnreset     ; TCPS_CLOSE_WAIT
758
        dd      .econnreset     ; TCPS_CLOSE_WAIT
760
        dd      .econnreset     ; TCPS_FIN_WAIT_1
759
        dd      .econnreset     ; TCPS_FIN_WAIT_1
761
        dd      .rst_close      ; TCPS_CLOSING
760
        dd      .rst_close      ; TCPS_CLOSING
762
        dd      .rst_close      ; TCPS_LAST_ACK
761
        dd      .rst_close      ; TCPS_LAST_ACK
763
        dd      .econnreset     ; TCPS_FIN_WAIT_2
762
        dd      .econnreset     ; TCPS_FIN_WAIT_2
764
        dd      .rst_close      ; TCPS_TIMED_WAIT
763
        dd      .rst_close      ; TCPS_TIMED_WAIT
765
 
764
 
766
  .econnrefused:
765
  .econnrefused:
767
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_input: Connection refused\n"
766
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_input: Connection refused\n"
768
 
767
 
769
        mov     [ebx + SOCKET.errorcode], ECONNREFUSED
768
        mov     [ebx + SOCKET.errorcode], ECONNREFUSED
770
        jmp     .close
769
        jmp     .close
771
 
770
 
772
  .econnreset:
771
  .econnreset:
773
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_input: Connection reset\n"
772
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_input: Connection reset\n"
774
 
773
 
775
        mov     [ebx + SOCKET.errorcode], ECONNRESET
774
        mov     [ebx + SOCKET.errorcode], ECONNRESET
776
 
775
 
777
  .close:
776
  .close:
778
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_input: Closing connection\n"
777
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_input: Closing connection\n"
779
 
778
 
780
        mov     [ebx + TCP_SOCKET.t_state], TCPS_CLOSED
779
        mov     [ebx + TCP_SOCKET.t_state], TCPS_CLOSED
781
;;; TODO: update stats (tcp drops)
780
;;; TODO: update stats (tcp drops)
782
        mov     eax, ebx
781
        mov     eax, ebx
783
        call    TCP_close
782
        call    TCP_close
784
        jmp     .drop_no_socket
783
        jmp     .drop_no_socket
785
 
784
 
786
  .rst_close:
785
  .rst_close:
787
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_input: Closing with reset\n"
786
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_input: Closing with reset\n"
788
 
787
 
789
        mov     eax, ebx
788
        mov     eax, ebx
790
        call    TCP_close
789
        call    TCP_close
791
        jmp     .drop_no_socket
790
        jmp     .drop_no_socket
792
 
791
 
793
  .no_rst:
792
  .no_rst:
794
 
793
 
795
;--------------------------------------
794
;--------------------------------------
796
; handle SYN-full and ACK-less segments
795
; handle SYN-full and ACK-less segments
797
 
796
 
798
        test    [edx + TCP_header.Flags], TH_SYN
797
        test    [edx + TCP_header.Flags], TH_SYN
799
        jz      .not_syn_full
798
        jz      .not_syn_full
800
 
799
 
801
        mov     eax, ebx
800
        mov     eax, ebx
802
        mov     ebx, ECONNRESET
801
        mov     ebx, ECONNRESET
803
        call    TCP_drop
802
        call    TCP_drop
804
        jmp     .drop_with_reset
803
        jmp     .drop_with_reset
805
  .not_syn_full:
804
  .not_syn_full:
806
 
805
 
807
;---------------
806
;---------------
808
; ACK processing
807
; ACK processing
809
 
808
 
810
        test    [edx + TCP_header.Flags], TH_ACK
809
        test    [edx + TCP_header.Flags], TH_ACK
811
        jz      .drop
810
        jz      .drop
812
 
811
 
813
        cmp     [ebx + TCP_SOCKET.t_state], TCPS_SYN_RECEIVED
812
        cmp     [ebx + TCP_SOCKET.t_state], TCPS_SYN_RECEIVED
814
        jb      .ack_processed                                  ; states: closed, listen, syn_sent
813
        jb      .ack_processed                                  ; states: closed, listen, syn_sent
815
        ja      .no_syn_rcv                                     ; established, fin_wait_1, fin_wait_2, close_wait, closing, last_ack, time_wait
814
        ja      .no_syn_rcv                                     ; established, fin_wait_1, fin_wait_2, close_wait, closing, last_ack, time_wait
816
 
815
 
817
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_input: state=syn_received\n"
816
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_input: state=syn_received\n"
818
 
817
 
819
        mov     eax, [edx + TCP_header.AckNumber]
818
        mov     eax, [edx + TCP_header.AckNumber]
820
        cmp     [ebx + TCP_SOCKET.SND_UNA], eax
819
        cmp     [ebx + TCP_SOCKET.SND_UNA], eax
821
        ja      .drop_with_reset
820
        ja      .drop_with_reset
822
        cmp     eax, [ebx + TCP_SOCKET.SND_MAX]
821
        cmp     eax, [ebx + TCP_SOCKET.SND_MAX]
823
        ja      .drop_with_reset
822
        ja      .drop_with_reset
824
 
823
 
825
;;; TODO: update stats
824
;;; TODO: update stats
826
 
825
 
827
        mov     eax, ebx
826
        mov     eax, ebx
828
        call    SOCKET_is_connected
827
        call    SOCKET_is_connected
829
        mov     [ebx + TCP_SOCKET.t_state], TCPS_ESTABLISHED
828
        mov     [ebx + TCP_SOCKET.t_state], TCPS_ESTABLISHED
830
 
829
 
831
; Do window scaling?
830
; Do window scaling?
832
 
831
 
833
        test    [ebx + TCP_SOCKET.t_flags], TF_RCVD_SCALE
832
        test    [ebx + TCP_SOCKET.t_flags], TF_RCVD_SCALE
834
        jz      @f
833
        jz      @f
835
        test    [ebx + TCP_SOCKET.t_flags], TF_REQ_SCALE
834
        test    [ebx + TCP_SOCKET.t_flags], TF_REQ_SCALE
836
        jz      @f
835
        jz      @f
837
 
836
 
838
        push    word [ebx + TCP_SOCKET.requested_s_scale]       ; Set send and receive scale factors to the received values
837
        push    word [ebx + TCP_SOCKET.requested_s_scale]       ; Set send and receive scale factors to the received values
839
        pop     word [ebx + TCP_SOCKET.SND_SCALE]
838
        pop     word [ebx + TCP_SOCKET.SND_SCALE]
840
       @@:
839
       @@:
841
 
840
 
842
        call    TCP_reassemble
841
        call    TCP_reassemble
843
 
842
 
844
        mov     eax, [edx + TCP_header.SequenceNumber]
843
        mov     eax, [edx + TCP_header.SequenceNumber]
845
        dec     eax
844
        dec     eax
846
        mov     [ebx + TCP_SOCKET.SND_WL1], eax
845
        mov     [ebx + TCP_SOCKET.SND_WL1], eax
847
 
846
 
848
  .no_syn_rcv:
847
  .no_syn_rcv:
849
 
848
 
850
;-------------------------
849
;-------------------------
851
; check for duplicate ACKs
850
; check for duplicate ACKs
852
 
851
 
853
        mov     eax, [edx + TCP_header.AckNumber]
852
        mov     eax, [edx + TCP_header.AckNumber]
854
        cmp     eax, [ebx + TCP_SOCKET.SND_UNA]
853
        cmp     eax, [ebx + TCP_SOCKET.SND_UNA]
855
        ja      .not_dup_ack
854
        ja      .not_dup_ack
856
 
855
 
857
        test    ecx, ecx
856
        test    ecx, ecx
858
        jnz     .reset_dupacks
857
        jnz     .reset_dupacks
859
 
858
 
860
        mov     eax, dword [edx + TCP_header.Window]
859
        mov     eax, dword [edx + TCP_header.Window]
861
        cmp     eax, [ebx + TCP_SOCKET.SND_WND]
860
        cmp     eax, [ebx + TCP_SOCKET.SND_WND]
862
        jne     .reset_dupacks
861
        jne     .reset_dupacks
863
 
862
 
864
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_input: Processing duplicate ACK\n"
863
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_input: Processing duplicate ACK\n"
865
 
864
 
866
; If we have outstanding data, other than a window probe, this is a completely duplicate ACK
865
; If we have outstanding data, other than a window probe, this is a completely duplicate ACK
867
; (window info didnt change) The ACK is the biggest we've seen and we've seen exactly our rexmt threshold of them,
866
; (window info didnt change) The ACK is the biggest we've seen and we've seen exactly our rexmt threshold of them,
868
; assume a packet has been dropped and retransmit it. Kludge snd_nxt & the congestion window so we send only this one packet.
867
; assume a packet has been dropped and retransmit it. Kludge snd_nxt & the congestion window so we send only this one packet.
869
 
868
 
870
        test    [ebx + TCP_SOCKET.timer_flags], timer_flag_retransmission
869
        test    [ebx + TCP_SOCKET.timer_flags], timer_flag_retransmission
871
        jz      @f
870
        jz      @f
872
 
871
 
873
        mov     eax, [edx + TCP_header.AckNumber]
872
        mov     eax, [edx + TCP_header.AckNumber]
874
        cmp     eax, [ebx + TCP_SOCKET.SND_UNA]
873
        cmp     eax, [ebx + TCP_SOCKET.SND_UNA]
875
        je      .dup_ack
874
        je      .dup_ack
876
 
875
 
877
       @@:
876
       @@:
878
        mov     [ebx + TCP_SOCKET.t_dupacks], 0
877
        mov     [ebx + TCP_SOCKET.t_dupacks], 0
879
        jmp     .not_dup_ack
878
        jmp     .not_dup_ack
880
 
879
 
881
  .dup_ack:
880
  .dup_ack:
882
        inc     [ebx + TCP_SOCKET.t_dupacks]
881
        inc     [ebx + TCP_SOCKET.t_dupacks]
883
        cmp     [ebx + TCP_SOCKET.t_dupacks], TCP_re_xmit_thresh
882
        cmp     [ebx + TCP_SOCKET.t_dupacks], TCP_re_xmit_thresh
884
        jne     .no_re_xmit
883
        jne     .no_re_xmit
885
 
884
 
886
        push    [ebx + TCP_SOCKET.SND_NXT]              ; >>>>
885
        push    [ebx + TCP_SOCKET.SND_NXT]              ; >>>>
887
 
886
 
888
        mov     eax, [ebx + TCP_SOCKET.SND_WND]
887
        mov     eax, [ebx + TCP_SOCKET.SND_WND]
889
        cmp     eax, [ebx + TCP_SOCKET.SND_CWND]
888
        cmp     eax, [ebx + TCP_SOCKET.SND_CWND]
890
        jbe     @f
889
        jbe     @f
891
        mov     eax, [ebx + TCP_SOCKET.SND_CWND]
890
        mov     eax, [ebx + TCP_SOCKET.SND_CWND]
892
  @@:
891
  @@:
893
        shr     eax, 1
892
        shr     eax, 1
894
        push    edx
893
        push    edx
895
        xor     edx, edx
894
        xor     edx, edx
896
        div     [ebx + TCP_SOCKET.t_maxseg]
895
        div     [ebx + TCP_SOCKET.t_maxseg]
897
        cmp     eax, 2
896
        cmp     eax, 2
898
        ja      @f
897
        ja      @f
899
        xor     eax, eax
898
        xor     eax, eax
900
        mov     al, 2
899
        mov     al, 2
901
       @@:
900
       @@:
902
        mul     [ebx + TCP_SOCKET.t_maxseg]
901
        mul     [ebx + TCP_SOCKET.t_maxseg]
903
        pop     edx
902
        pop     edx
904
        mov     [ebx + TCP_SOCKET.SND_SSTHRESH], eax
903
        mov     [ebx + TCP_SOCKET.SND_SSTHRESH], eax
905
 
904
 
906
        and     [ebx + TCP_SOCKET.timer_flags], not timer_flag_retransmission   ; turn off retransmission timer
905
        and     [ebx + TCP_SOCKET.timer_flags], not timer_flag_retransmission   ; turn off retransmission timer
907
        mov     [ebx + TCP_SOCKET.t_rtt], 0
906
        mov     [ebx + TCP_SOCKET.t_rtt], 0
908
        mov     eax, [edx + TCP_header.AckNumber]
907
        mov     eax, [edx + TCP_header.AckNumber]
909
        mov     [ebx + TCP_SOCKET.SND_NXT], eax
908
        mov     [ebx + TCP_SOCKET.SND_NXT], eax
910
        mov     eax, [ebx + TCP_SOCKET.t_maxseg]
909
        mov     eax, [ebx + TCP_SOCKET.t_maxseg]
911
        mov     [ebx + TCP_SOCKET.SND_CWND], eax
910
        mov     [ebx + TCP_SOCKET.SND_CWND], eax
912
 
911
 
913
; Unlock the socket
912
; Unlock the socket
914
        push    ebx
913
        push    ebx
915
        lea     ecx, [ebx + SOCKET.mutex]
914
        lea     ecx, [ebx + SOCKET.mutex]
916
        call    mutex_unlock
915
        call    mutex_unlock
917
 
916
 
918
; retransmit missing segment
917
; retransmit missing segment
919
        mov     eax, [esp]
918
        mov     eax, [esp]
920
        call    TCP_output
919
        call    TCP_output
921
 
920
 
922
; Lock the socket again
921
; Lock the socket again
923
        mov     ecx, [esp]
922
        mov     ecx, [esp]
924
        add     ecx, SOCKET.mutex
923
        add     ecx, SOCKET.mutex
925
        call    mutex_lock
924
        call    mutex_lock
926
        pop     ebx
925
        pop     ebx
927
 
926
 
928
; Continue processing
927
; Continue processing
929
        xor     edx, edx
928
        xor     edx, edx
930
        mov     eax, [ebx + TCP_SOCKET.t_maxseg]
929
        mov     eax, [ebx + TCP_SOCKET.t_maxseg]
931
        mul     [ebx + TCP_SOCKET.t_dupacks]
930
        mul     [ebx + TCP_SOCKET.t_dupacks]
932
        add     eax, [ebx + TCP_SOCKET.SND_SSTHRESH]
931
        add     eax, [ebx + TCP_SOCKET.SND_SSTHRESH]
933
        mov     [ebx + TCP_SOCKET.SND_CWND], eax
932
        mov     [ebx + TCP_SOCKET.SND_CWND], eax
934
 
933
 
935
        pop     eax                                     ; <<<<
934
        pop     eax                                     ; <<<<
936
        cmp     eax, [ebx + TCP_SOCKET.SND_NXT]
935
        cmp     eax, [ebx + TCP_SOCKET.SND_NXT]
937
        jb      @f
936
        jb      @f
938
        mov     [ebx + TCP_SOCKET.SND_NXT], eax
937
        mov     [ebx + TCP_SOCKET.SND_NXT], eax
939
       @@:
938
       @@:
940
 
939
 
941
        jmp     .drop
940
        jmp     .drop
942
 
941
 
943
 
942
 
944
  .no_re_xmit:
943
  .no_re_xmit:
945
        jbe     .not_dup_ack
944
        jbe     .not_dup_ack
946
 
945
 
947
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_input: Increasing congestion window\n"
946
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_input: Increasing congestion window\n"
948
 
947
 
949
        mov     eax, [ebx + TCP_SOCKET.t_maxseg]
948
        mov     eax, [ebx + TCP_SOCKET.t_maxseg]
950
        add     [ebx + TCP_SOCKET.SND_CWND], eax
949
        add     [ebx + TCP_SOCKET.SND_CWND], eax
951
 
950
 
952
; Unlock the socket
951
; Unlock the socket
953
        push    ebx
952
        push    ebx
954
        lea     ecx, [ebx + SOCKET.mutex]
953
        lea     ecx, [ebx + SOCKET.mutex]
955
        call    mutex_unlock
954
        call    mutex_unlock
956
 
955
 
957
; retransmit missing segment
956
; retransmit missing segment
958
        mov     eax, [esp]
957
        mov     eax, [esp]
959
        call    TCP_output
958
        call    TCP_output
960
 
959
 
961
; Lock the socket again
960
; Lock the socket again
962
        mov     ecx, [esp]
961
        mov     ecx, [esp]
963
        add     ecx, SOCKET.mutex
962
        add     ecx, SOCKET.mutex
964
        call    mutex_lock
963
        call    mutex_lock
965
        pop     ebx
964
        pop     ebx
966
 
965
 
967
        jmp     .drop
966
        jmp     .drop
968
 
967
 
969
 
968
 
970
  .not_dup_ack:
969
  .not_dup_ack:
971
 
970
 
972
;-------------------------------------------------
971
;-------------------------------------------------
973
; If the congestion window was inflated to account
972
; If the congestion window was inflated to account
974
; for the other side's cached packets, retract it
973
; for the other side's cached packets, retract it
975
 
974
 
976
        mov     eax, [ebx + TCP_SOCKET.SND_SSTHRESH]
975
        mov     eax, [ebx + TCP_SOCKET.SND_SSTHRESH]
977
        cmp     eax, [ebx + TCP_SOCKET.SND_CWND]
976
        cmp     eax, [ebx + TCP_SOCKET.SND_CWND]
978
        ja      @f
977
        ja      @f
979
        cmp     [ebx + TCP_SOCKET.t_dupacks], TCP_re_xmit_thresh
978
        cmp     [ebx + TCP_SOCKET.t_dupacks], TCP_re_xmit_thresh
980
        jbe     @f
979
        jbe     @f
981
        mov     [ebx + TCP_SOCKET.SND_CWND], eax
980
        mov     [ebx + TCP_SOCKET.SND_CWND], eax
982
       @@:
981
       @@:
983
 
982
 
984
        mov     [ebx + TCP_SOCKET.t_dupacks], 0
983
        mov     [ebx + TCP_SOCKET.t_dupacks], 0
985
 
984
 
986
        mov     eax, [edx + TCP_header.AckNumber]
985
        mov     eax, [edx + TCP_header.AckNumber]
987
        cmp     eax, [ebx + TCP_SOCKET.SND_MAX]
986
        cmp     eax, [ebx + TCP_SOCKET.SND_MAX]
988
        jbe     @f
987
        jbe     @f
989
        inc     [TCPS_rcvacktoomuch]
988
        inc     [TCPS_rcvacktoomuch]
990
        jmp     .drop_after_ack
989
        jmp     .drop_after_ack
991
       @@:
990
       @@:
992
 
991
 
993
        mov     edi, [edx + TCP_header.AckNumber]
992
        mov     edi, [edx + TCP_header.AckNumber]
994
        sub     edi, [ebx + TCP_SOCKET.SND_UNA]         ; now we got the number of acked bytes in edi
993
        sub     edi, [ebx + TCP_SOCKET.SND_UNA]         ; now we got the number of acked bytes in edi
995
        inc     [TCPS_rcvackpack]
994
        inc     [TCPS_rcvackpack]
996
        add     [TCPS_rcvackbyte], edi
995
        add     [TCPS_rcvackbyte], edi
997
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_input: acceptable ACK for %u bytes\n", edi
996
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_input: acceptable ACK for %u bytes\n", edi
998
 
997
 
999
;------------------------------------------
998
;------------------------------------------
1000
; RTT measurements and retransmission timer
999
; RTT measurements and retransmission timer
1001
 
1000
 
1002
; If we have a timestamp, update smoothed RTT
1001
; If we have a timestamp, update smoothed RTT
1003
 
1002
 
1004
        test    [temp_bits], TCP_BIT_TIMESTAMP
1003
        test    [temp_bits], TCP_BIT_TIMESTAMP
1005
        jz      .timestamp_not_present
1004
        jz      .timestamp_not_present
1006
        mov     eax, [timestamp]
1005
        mov     eax, [timestamp]
1007
        sub     eax, [ebx + TCP_SOCKET.ts_ecr]
1006
        sub     eax, [ebx + TCP_SOCKET.ts_ecr]
1008
        inc     eax
1007
        inc     eax
1009
        call    TCP_xmit_timer
1008
        call    TCP_xmit_timer
1010
        jmp     .rtt_done_
1009
        jmp     .rtt_done_
1011
 
1010
 
1012
; If no timestamp but transmit timer is running and timed sequence number was acked,
1011
; If no timestamp but transmit timer is running and timed sequence number was acked,
1013
; update smoothed RTT. Since we now have an RTT measurement, cancel the timer backoff
1012
; update smoothed RTT. Since we now have an RTT measurement, cancel the timer backoff
1014
; (Phil Karn's retransmit algo)
1013
; (Phil Karn's retransmit algo)
1015
; Recompute the initial retransmit timer
1014
; Recompute the initial retransmit timer
1016
 
1015
 
1017
  .timestamp_not_present:
1016
  .timestamp_not_present:
1018
        mov     eax, [edx + TCP_header.AckNumber]
1017
        mov     eax, [edx + TCP_header.AckNumber]
1019
        cmp     eax, [ebx + TCP_SOCKET.t_rtseq]
1018
        cmp     eax, [ebx + TCP_SOCKET.t_rtseq]
1020
        jbe     .rtt_done_
1019
        jbe     .rtt_done_
1021
        mov     eax, [ebx + TCP_SOCKET.t_rtt]
1020
        mov     eax, [ebx + TCP_SOCKET.t_rtt]
1022
        test    eax, eax
1021
        test    eax, eax
1023
        jz      .rtt_done_
1022
        jz      .rtt_done_
1024
        call    TCP_xmit_timer
1023
        call    TCP_xmit_timer
1025
 
1024
 
1026
  .rtt_done_:
1025
  .rtt_done_:
1027
 
1026
 
1028
; If all outstanding data is acked, stop retransmit timer and remember to restart (more output or persist)
1027
; If all outstanding data is acked, stop retransmit timer and remember to restart (more output or persist)
1029
; If there is more data to be acked, restart retransmit timer, using current (possible backed-off) value.
1028
; If there is more data to be acked, restart retransmit timer, using current (possible backed-off) value.
1030
 
1029
 
1031
        mov     eax, [ebx + TCP_SOCKET.SND_MAX]
1030
        mov     eax, [ebx + TCP_SOCKET.SND_MAX]
1032
        cmp     eax, [edx + TCP_header.AckNumber]
1031
        cmp     eax, [edx + TCP_header.AckNumber]
1033
        jne     .more_data
1032
        jne     .more_data
1034
        and     [ebx + TCP_SOCKET.timer_flags], not timer_flag_retransmission
1033
        and     [ebx + TCP_SOCKET.timer_flags], not timer_flag_retransmission
1035
        or      [temp_bits], TCP_BIT_NEEDOUTPUT
1034
        or      [temp_bits], TCP_BIT_NEEDOUTPUT
1036
        jmp     .no_restart
1035
        jmp     .no_restart
1037
  .more_data:
1036
  .more_data:
1038
        test    [ebx + TCP_SOCKET.timer_flags], timer_flag_persist
1037
        test    [ebx + TCP_SOCKET.timer_flags], timer_flag_persist
1039
        jnz     .no_restart
1038
        jnz     .no_restart
1040
 
1039
 
1041
        mov     eax, [ebx + TCP_SOCKET.t_rxtcur]
1040
        mov     eax, [ebx + TCP_SOCKET.t_rxtcur]
1042
        mov     [ebx + TCP_SOCKET.timer_retransmission], eax
1041
        mov     [ebx + TCP_SOCKET.timer_retransmission], eax
1043
        or      [ebx + TCP_SOCKET.timer_flags], timer_flag_retransmission
1042
        or      [ebx + TCP_SOCKET.timer_flags], timer_flag_retransmission
1044
  .no_restart:
1043
  .no_restart:
1045
 
1044
 
1046
 
1045
 
1047
;-------------------------------------------
1046
;-------------------------------------------
1048
; Open congestion window in response to ACKs
1047
; Open congestion window in response to ACKs
1049
 
1048
 
1050
        mov     esi, [ebx + TCP_SOCKET.SND_CWND]
1049
        mov     esi, [ebx + TCP_SOCKET.SND_CWND]
1051
        mov     eax, [ebx + TCP_SOCKET.t_maxseg]
1050
        mov     eax, [ebx + TCP_SOCKET.t_maxseg]
1052
 
1051
 
1053
        cmp     esi, [ebx + TCP_SOCKET.SND_SSTHRESH]
1052
        cmp     esi, [ebx + TCP_SOCKET.SND_SSTHRESH]
1054
        jbe     @f
1053
        jbe     @f
1055
        push    edx
1054
        push    edx
1056
        push    eax
1055
        push    eax
1057
        mul     eax
1056
        mul     eax
1058
        div     esi
1057
        div     esi
1059
        pop     edx
1058
        pop     edx
1060
        shr     edx, 3
1059
        shr     edx, 3
1061
        add     eax, edx
1060
        add     eax, edx
1062
        pop     edx
1061
        pop     edx
1063
       @@:
1062
       @@:
1064
 
1063
 
1065
        add     esi, eax
1064
        add     esi, eax
1066
 
1065
 
1067
        push    ecx
1066
        push    ecx
1068
        mov     cl, [ebx + TCP_SOCKET.SND_SCALE]
1067
        mov     cl, [ebx + TCP_SOCKET.SND_SCALE]
1069
        mov     eax, TCP_max_win
1068
        mov     eax, TCP_max_win
1070
        shl     eax, cl
1069
        shl     eax, cl
1071
        pop     ecx
1070
        pop     ecx
1072
 
1071
 
1073
        cmp     esi, eax
1072
        cmp     esi, eax
1074
        jbe     @f
1073
        jbe     @f
1075
        mov     esi, eax
1074
        mov     esi, eax
1076
  @@:
1075
  @@:
1077
        mov     [ebx + TCP_SOCKET.SND_CWND], esi
1076
        mov     [ebx + TCP_SOCKET.SND_CWND], esi
1078
 
1077
 
1079
;------------------------------------------
1078
;------------------------------------------
1080
; Remove acknowledged data from send buffer
1079
; Remove acknowledged data from send buffer
1081
 
1080
 
1082
        cmp     edi, [ebx + STREAM_SOCKET.snd.size]
1081
        cmp     edi, [ebx + STREAM_SOCKET.snd.size]
1083
        jbe     .finiacked
1082
        jbe     .finiacked
1084
 
1083
 
1085
        push    ecx edx ebx
1084
        push    ecx edx ebx
1086
        mov     ecx, [ebx + STREAM_SOCKET.snd.size]
1085
        mov     ecx, [ebx + STREAM_SOCKET.snd.size]
1087
        lea     eax, [ebx + STREAM_SOCKET.snd]
1086
        lea     eax, [ebx + STREAM_SOCKET.snd]
1088
        sub     [ebx + TCP_SOCKET.SND_WND], ecx
1087
        sub     [ebx + TCP_SOCKET.SND_WND], ecx
1089
        call    SOCKET_ring_free
1088
        call    SOCKET_ring_free
1090
        pop     ebx edx ecx
1089
        pop     ebx edx ecx
1091
 
1090
 
1092
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_input: our FIN is acked\n"
1091
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_input: our FIN is acked\n"
1093
        or      [temp_bits], TCP_BIT_FIN_IS_ACKED
1092
        or      [temp_bits], TCP_BIT_FIN_IS_ACKED
1094
        jmp     .wakeup
1093
        jmp     .wakeup
1095
 
1094
 
1096
  .finiacked:
1095
  .finiacked:
1097
 
1096
 
1098
        push    ecx edx ebx
1097
        push    ecx edx ebx
1099
        mov     ecx, edi
1098
        mov     ecx, edi
1100
        lea     eax, [ebx + STREAM_SOCKET.snd]
1099
        lea     eax, [ebx + STREAM_SOCKET.snd]
1101
        call    SOCKET_ring_free
1100
        call    SOCKET_ring_free
1102
        pop     ebx
1101
        pop     ebx
1103
        sub     [ebx + TCP_SOCKET.SND_WND], ecx
1102
        sub     [ebx + TCP_SOCKET.SND_WND], ecx
1104
        pop     edx ecx
1103
        pop     edx ecx
1105
 
1104
 
1106
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_input: our FIN is not acked\n"
1105
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_input: our FIN is not acked\n"
1107
 
1106
 
1108
;----------------------------------------
1107
;----------------------------------------
1109
; Wake up process waiting on send buffer
1108
; Wake up process waiting on send buffer
1110
 
1109
 
1111
  .wakeup:
1110
  .wakeup:
1112
        mov     eax, ebx
1111
        mov     eax, ebx
1113
        call    SOCKET_notify
1112
        call    SOCKET_notify
1114
 
1113
 
1115
; Update TCPS
1114
; Update TCPS
1116
        mov     eax, [edx + TCP_header.AckNumber]
1115
        mov     eax, [edx + TCP_header.AckNumber]
1117
        mov     [ebx + TCP_SOCKET.SND_UNA], eax
1116
        mov     [ebx + TCP_SOCKET.SND_UNA], eax
1118
        cmp     eax, [ebx + TCP_SOCKET.SND_NXT]
1117
        cmp     eax, [ebx + TCP_SOCKET.SND_NXT]
1119
        jb      @f
1118
        jb      @f
1120
        mov     [ebx + TCP_SOCKET.SND_NXT], eax
1119
        mov     [ebx + TCP_SOCKET.SND_NXT], eax
1121
       @@:
1120
       @@:
1122
 
1121
 
1123
; General ACK handling complete
1122
; General ACK handling complete
1124
; Now do the state-specific ones
1123
; Now do the state-specific ones
1125
; Carry flag is set when our FIN is acked
1124
; Carry flag is set when our FIN is acked
1126
 
1125
 
1127
        mov     eax, [ebx + TCP_SOCKET.t_state]
1126
        mov     eax, [ebx + TCP_SOCKET.t_state]
1128
        jmp     dword [eax*4 + .ACK_sw_list]
1127
        jmp     dword [eax*4 + .ACK_sw_list]
1129
 
1128
 
1130
  .ACK_sw_list:
1129
  .ACK_sw_list:
1131
        dd      .ack_processed  ; TCPS_CLOSED
1130
        dd      .ack_processed  ; TCPS_CLOSED
1132
        dd      .ack_processed  ; TCPS_LISTEN
1131
        dd      .ack_processed  ; TCPS_LISTEN
1133
        dd      .ack_processed  ; TCPS_SYN_SENT
1132
        dd      .ack_processed  ; TCPS_SYN_SENT
1134
        dd      .ack_processed  ; TCPS_SYN_RECEIVED
1133
        dd      .ack_processed  ; TCPS_SYN_RECEIVED
1135
        dd      .ack_processed  ; TCPS_ESTABLISHED
1134
        dd      .ack_processed  ; TCPS_ESTABLISHED
1136
        dd      .ack_processed  ; TCPS_CLOSE_WAIT
1135
        dd      .ack_processed  ; TCPS_CLOSE_WAIT
1137
        dd      .ack_fw1        ; TCPS_FIN_WAIT_1
1136
        dd      .ack_fw1        ; TCPS_FIN_WAIT_1
1138
        dd      .ack_c          ; TCPS_CLOSING
1137
        dd      .ack_c          ; TCPS_CLOSING
1139
        dd      .ack_la         ; TCPS_LAST_ACK
1138
        dd      .ack_la         ; TCPS_LAST_ACK
1140
        dd      .ack_processed  ; TCPS_FIN_WAIT_2
1139
        dd      .ack_processed  ; TCPS_FIN_WAIT_2
1141
        dd      .ack_tw         ; TCPS_TIMED_WAIT
1140
        dd      .ack_tw         ; TCPS_TIMED_WAIT
1142
 
1141
 
1143
 
1142
 
1144
  .ack_fw1:
1143
  .ack_fw1:
1145
        test    [temp_bits], TCP_BIT_FIN_IS_ACKED
1144
        test    [temp_bits], TCP_BIT_FIN_IS_ACKED
1146
        jz      .ack_processed
1145
        jz      .ack_processed
1147
 
1146
 
1148
        test    [ebx + SOCKET.state], SS_CANTRCVMORE
1147
        test    [ebx + SOCKET.state], SS_CANTRCVMORE
1149
        jnz     @f
1148
        jnz     @f
1150
        mov     eax, ebx
1149
        mov     eax, ebx
1151
        call    SOCKET_is_disconnected
1150
        call    SOCKET_is_disconnected
1152
        mov     [ebx + TCP_SOCKET.timer_timed_wait], TCP_time_max_idle
1151
        mov     [ebx + TCP_SOCKET.timer_timed_wait], TCP_time_max_idle
1153
        or      [ebx + TCP_SOCKET.timer_flags], timer_flag_wait
1152
        or      [ebx + TCP_SOCKET.timer_flags], timer_flag_wait
1154
       @@:
1153
       @@:
1155
        mov     [ebx + TCP_SOCKET.t_state], TCPS_FIN_WAIT_2
1154
        mov     [ebx + TCP_SOCKET.t_state], TCPS_FIN_WAIT_2
1156
        jmp     .ack_processed
1155
        jmp     .ack_processed
1157
 
1156
 
1158
  .ack_c:
1157
  .ack_c:
1159
        test    [temp_bits], TCP_BIT_FIN_IS_ACKED
1158
        test    [temp_bits], TCP_BIT_FIN_IS_ACKED
1160
        jz      .ack_processed
1159
        jz      .ack_processed
1161
 
1160
 
1162
        mov     [ebx + TCP_SOCKET.t_state], TCPS_TIMED_WAIT
1161
        mov     [ebx + TCP_SOCKET.t_state], TCPS_TIMED_WAIT
1163
        mov     eax, ebx
1162
        mov     eax, ebx
1164
        call    TCP_cancel_timers
1163
        call    TCP_cancel_timers
1165
        mov     [ebx + TCP_SOCKET.timer_timed_wait], 2 * TCP_time_MSL
1164
        mov     [ebx + TCP_SOCKET.timer_timed_wait], 2 * TCP_time_MSL
1166
        or      [ebx + TCP_SOCKET.timer_flags], timer_flag_wait
1165
        or      [ebx + TCP_SOCKET.timer_flags], timer_flag_wait
1167
        mov     eax, ebx
1166
        mov     eax, ebx
1168
        call    SOCKET_is_disconnected
1167
        call    SOCKET_is_disconnected
1169
        jmp     .ack_processed
1168
        jmp     .ack_processed
1170
 
1169
 
1171
  .ack_la:
1170
  .ack_la:
1172
        test    [temp_bits], TCP_BIT_FIN_IS_ACKED
1171
        test    [temp_bits], TCP_BIT_FIN_IS_ACKED
1173
        jz      .ack_processed
1172
        jz      .ack_processed
1174
 
1173
 
1175
        push    ebx
1174
        push    ebx
1176
        lea     ecx, [ebx + SOCKET.mutex]
1175
        lea     ecx, [ebx + SOCKET.mutex]
1177
        call    mutex_unlock
1176
        call    mutex_unlock
1178
        pop     ebx
1177
        pop     ebx
1179
 
1178
 
1180
        mov     eax, ebx
1179
        mov     eax, ebx
1181
        call    TCP_close
1180
        call    TCP_close
1182
        jmp     .drop_no_socket
1181
        jmp     .drop_no_socket
1183
 
1182
 
1184
  .ack_tw:
1183
  .ack_tw:
1185
        mov     [ebx + TCP_SOCKET.timer_timed_wait], 2 * TCP_time_MSL
1184
        mov     [ebx + TCP_SOCKET.timer_timed_wait], 2 * TCP_time_MSL
1186
        or      [ebx + TCP_SOCKET.timer_flags], timer_flag_wait
1185
        or      [ebx + TCP_SOCKET.timer_flags], timer_flag_wait
1187
        jmp     .drop_after_ack
1186
        jmp     .drop_after_ack
1188
 
1187
 
1189
  .reset_dupacks:               ; We got a new ACK, reset duplicate ACK counter
1188
  .reset_dupacks:               ; We got a new ACK, reset duplicate ACK counter
1190
        mov     [ebx + TCP_SOCKET.t_dupacks], 0
1189
        mov     [ebx + TCP_SOCKET.t_dupacks], 0
1191
        jmp     .ack_processed
1190
        jmp     .ack_processed
1192
 
1191
 
1193
;-------
1192
;-------
1194
; LISTEN
1193
; LISTEN
1195
 
1194
 
1196
align 4
1195
align 4
1197
  .LISTEN:
1196
  .LISTEN:
1198
 
1197
 
1199
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_input: state=listen\n"
1198
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_input: state=listen\n"
1200
 
1199
 
1201
        test    [edx + TCP_header.Flags], TH_RST
1200
        test    [edx + TCP_header.Flags], TH_RST
1202
        jnz     .drop
1201
        jnz     .drop
1203
 
1202
 
1204
        test    [edx + TCP_header.Flags], TH_ACK
1203
        test    [edx + TCP_header.Flags], TH_ACK
1205
        jnz     .drop_with_reset
1204
        jnz     .drop_with_reset
1206
 
1205
 
1207
        test    [edx + TCP_header.Flags], TH_SYN
1206
        test    [edx + TCP_header.Flags], TH_SYN
1208
        jz      .drop
1207
        jz      .drop
1209
 
1208
 
1210
        inc     [TCPS_accepts]                          ; update stats
1209
        inc     [TCPS_accepts]                          ; update stats
1211
 
1210
 
1212
;;; TODO: check if it's a broadcast or multicast, and drop if so
1211
;;; TODO: check if it's a broadcast or multicast, and drop if so
1213
 
1212
 
1214
        push    dword [edi]                             ; Ipv4 source addres
1213
        push    [edi + IPv4_header.SourceAddress]
1215
        pop     [ebx + IP_SOCKET.RemoteIP]
1214
        pop     [ebx + IP_SOCKET.RemoteIP]
1216
 
1215
 
1217
        push    [edx + TCP_header.SourcePort]
1216
        push    [edx + TCP_header.SourcePort]
1218
        pop     [ebx + TCP_SOCKET.RemotePort]
1217
        pop     [ebx + TCP_SOCKET.RemotePort]
1219
 
1218
 
1220
        push    [edx + TCP_header.SequenceNumber]
1219
        push    [edx + TCP_header.SequenceNumber]
1221
        pop     [ebx + TCP_SOCKET.IRS]
1220
        pop     [ebx + TCP_SOCKET.IRS]
1222
 
1221
 
1223
        mov     eax, [TCP_sequence_num]
1222
        mov     eax, [TCP_sequence_num]
1224
        add     [TCP_sequence_num], 64000 / 2
1223
        add     [TCP_sequence_num], 64000 / 2
1225
        mov     [ebx + TCP_SOCKET.ISS], eax
1224
        mov     [ebx + TCP_SOCKET.ISS], eax
1226
        mov     [ebx + TCP_SOCKET.SND_NXT], eax
1225
        mov     [ebx + TCP_SOCKET.SND_NXT], eax
1227
 
1226
 
1228
        TCP_sendseqinit ebx
1227
        TCP_sendseqinit ebx
1229
        TCP_rcvseqinit ebx
1228
        TCP_rcvseqinit ebx
1230
 
1229
 
1231
        mov     [ebx + TCP_SOCKET.t_state], TCPS_SYN_RECEIVED
1230
        mov     [ebx + TCP_SOCKET.t_state], TCPS_SYN_RECEIVED
1232
        or      [ebx + TCP_SOCKET.t_flags], TF_ACKNOW
1231
        or      [ebx + TCP_SOCKET.t_flags], TF_ACKNOW
1233
        mov     [ebx + TCP_SOCKET.timer_keepalive], TCP_time_keep_interval  ;;;; macro
1232
        mov     [ebx + TCP_SOCKET.timer_keepalive], TCP_time_keep_interval  ;;;; macro
1234
        or      [ebx + TCP_SOCKET.timer_flags], timer_flag_keepalive
1233
        or      [ebx + TCP_SOCKET.timer_flags], timer_flag_keepalive
1235
 
1234
 
1236
        lea     eax, [ebx + STREAM_SOCKET.snd]
1235
        lea     eax, [ebx + STREAM_SOCKET.snd]
1237
        call    SOCKET_ring_create
1236
        call    SOCKET_ring_create
1238
        test    eax, eax
1237
        test    eax, eax
1239
        jz      .drop
1238
        jz      .drop
1240
 
1239
 
1241
        lea     eax, [ebx + STREAM_SOCKET.rcv]
1240
        lea     eax, [ebx + STREAM_SOCKET.rcv]
1242
        call    SOCKET_ring_create
1241
        call    SOCKET_ring_create
1243
        test    eax, eax
1242
        test    eax, eax
1244
        jz      .drop
1243
        jz      .drop
1245
 
1244
 
1246
        and     [temp_bits], not TCP_BIT_DROPSOCKET
1245
        and     [temp_bits], not TCP_BIT_DROPSOCKET
1247
 
1246
 
1248
        pusha
1247
        pusha
1249
        mov     eax, ebx
1248
        mov     eax, ebx
1250
        call    SOCKET_notify
1249
        call    SOCKET_notify
1251
        popa
1250
        popa
1252
 
1251
 
1253
        jmp     .trim
1252
        jmp     .trim
1254
 
1253
 
1255
;------------
1254
;------------
1256
; Active Open
1255
; Active Open
1257
 
1256
 
1258
align 4
1257
align 4
1259
  .SYN_SENT:
1258
  .SYN_SENT:
1260
 
1259
 
1261
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_input: state=syn_sent\n"
1260
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_input: state=syn_sent\n"
1262
 
1261
 
1263
        test    [edx + TCP_header.Flags], TH_ACK
1262
        test    [edx + TCP_header.Flags], TH_ACK
1264
        jz      @f
1263
        jz      @f
1265
 
1264
 
1266
        mov     eax, [edx + TCP_header.AckNumber]
1265
        mov     eax, [edx + TCP_header.AckNumber]
1267
        cmp     eax, [ebx + TCP_SOCKET.ISS]
1266
        cmp     eax, [ebx + TCP_SOCKET.ISS]
1268
        jbe     .drop_with_reset
1267
        jbe     .drop_with_reset
1269
 
1268
 
1270
        cmp     eax, [ebx + TCP_SOCKET.SND_MAX]
1269
        cmp     eax, [ebx + TCP_SOCKET.SND_MAX]
1271
        ja      .drop_with_reset
1270
        ja      .drop_with_reset
1272
       @@:
1271
       @@:
1273
 
1272
 
1274
        test    [edx + TCP_header.Flags], TH_RST
1273
        test    [edx + TCP_header.Flags], TH_RST
1275
        jz      @f
1274
        jz      @f
1276
 
1275
 
1277
        test    [edx + TCP_header.Flags], TH_ACK
1276
        test    [edx + TCP_header.Flags], TH_ACK
1278
        jz      .drop
1277
        jz      .drop
1279
 
1278
 
1280
        mov     eax, ebx
1279
        mov     eax, ebx
1281
        mov     ebx, ECONNREFUSED
1280
        mov     ebx, ECONNREFUSED
1282
        call    TCP_drop
1281
        call    TCP_drop
1283
 
1282
 
1284
        jmp     .drop
1283
        jmp     .drop
1285
       @@:
1284
       @@:
1286
 
1285
 
1287
        test    [edx + TCP_header.Flags], TH_SYN
1286
        test    [edx + TCP_header.Flags], TH_SYN
1288
        jz      .drop
1287
        jz      .drop
1289
 
1288
 
1290
; at this point, segment seems to be valid
1289
; at this point, segment seems to be valid
1291
 
1290
 
1292
        test    [edx + TCP_header.Flags], TH_ACK
1291
        test    [edx + TCP_header.Flags], TH_ACK
1293
        jz      .no_syn_ack
1292
        jz      .no_syn_ack
1294
 
1293
 
1295
; now, process received SYN in response to an active open
1294
; now, process received SYN in response to an active open
1296
 
1295
 
1297
        mov     eax, [edx + TCP_header.AckNumber]
1296
        mov     eax, [edx + TCP_header.AckNumber]
1298
        mov     [ebx + TCP_SOCKET.SND_UNA], eax
1297
        mov     [ebx + TCP_SOCKET.SND_UNA], eax
1299
        cmp     eax, [ebx + TCP_SOCKET.SND_NXT]
1298
        cmp     eax, [ebx + TCP_SOCKET.SND_NXT]
1300
        jbe     @f
1299
        jbe     @f
1301
        mov     [ebx + TCP_SOCKET.SND_NXT], eax
1300
        mov     [ebx + TCP_SOCKET.SND_NXT], eax
1302
       @@:
1301
       @@:
1303
 
1302
 
1304
  .no_syn_ack:
1303
  .no_syn_ack:
1305
        and     [ebx + TCP_SOCKET.timer_flags], not timer_flag_retransmission   ; disable retransmission timer
1304
        and     [ebx + TCP_SOCKET.timer_flags], not timer_flag_retransmission   ; disable retransmission timer
1306
 
1305
 
1307
        push    [edx + TCP_header.SequenceNumber]
1306
        push    [edx + TCP_header.SequenceNumber]
1308
        pop     [ebx + TCP_SOCKET.IRS]
1307
        pop     [ebx + TCP_SOCKET.IRS]
1309
 
1308
 
1310
        TCP_rcvseqinit ebx
1309
        TCP_rcvseqinit ebx
1311
 
1310
 
1312
        or      [ebx + TCP_SOCKET.t_flags], TF_ACKNOW
1311
        or      [ebx + TCP_SOCKET.t_flags], TF_ACKNOW
1313
 
1312
 
1314
        mov     eax, [ebx + TCP_SOCKET.SND_UNA]
1313
        mov     eax, [ebx + TCP_SOCKET.SND_UNA]
1315
        cmp     eax, [ebx + TCP_SOCKET.ISS]
1314
        cmp     eax, [ebx + TCP_SOCKET.ISS]
1316
        jbe     .simultaneous_open
1315
        jbe     .simultaneous_open
1317
 
1316
 
1318
        test    [edx + TCP_header.Flags], TH_ACK
1317
        test    [edx + TCP_header.Flags], TH_ACK
1319
        jz      .simultaneous_open
1318
        jz      .simultaneous_open
1320
 
1319
 
1321
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_input: active open\n"
1320
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_input: active open\n"
1322
 
1321
 
1323
;;; TODO: update stats
1322
;;; TODO: update stats
1324
 
1323
 
1325
; set socket state to connected
1324
; set socket state to connected
1326
        push    eax
1325
        push    eax
1327
        mov     eax, ebx
1326
        mov     eax, ebx
1328
        call    SOCKET_is_connected
1327
        call    SOCKET_is_connected
1329
        pop     eax
1328
        pop     eax
1330
        mov     [ebx + TCP_SOCKET.t_state], TCPS_ESTABLISHED
1329
        mov     [ebx + TCP_SOCKET.t_state], TCPS_ESTABLISHED
1331
 
1330
 
1332
; Do window scaling on this connection ?
1331
; Do window scaling on this connection ?
1333
        mov     eax, [ebx + TCP_SOCKET.t_flags]
1332
        mov     eax, [ebx + TCP_SOCKET.t_flags]
1334
        and     eax, TF_REQ_SCALE or TF_RCVD_SCALE
1333
        and     eax, TF_REQ_SCALE or TF_RCVD_SCALE
1335
        cmp     eax, TF_REQ_SCALE or TF_RCVD_SCALE
1334
        cmp     eax, TF_REQ_SCALE or TF_RCVD_SCALE
1336
        jne     .no_scaling
1335
        jne     .no_scaling
1337
 
1336
 
1338
        mov     ax, word [ebx + TCP_SOCKET.requested_s_scale]
1337
        mov     ax, word [ebx + TCP_SOCKET.requested_s_scale]
1339
        mov     word [ebx + TCP_SOCKET.SND_SCALE], ax
1338
        mov     word [ebx + TCP_SOCKET.SND_SCALE], ax
1340
  .no_scaling:
1339
  .no_scaling:
1341
 
1340
 
1342
;;; TODO: reassemble packets queue
1341
;;; TODO: reassemble packets queue
1343
 
1342
 
1344
        mov     eax, [ebx + TCP_SOCKET.t_rtt]
1343
        mov     eax, [ebx + TCP_SOCKET.t_rtt]
1345
        test    eax, eax
1344
        test    eax, eax
1346
        je      .trim
1345
        je      .trim
1347
        call    TCP_xmit_timer
1346
        call    TCP_xmit_timer
1348
        jmp     .trim
1347
        jmp     .trim
1349
 
1348
 
1350
  .simultaneous_open:
1349
  .simultaneous_open:
1351
 
1350
 
1352
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_input: simultaneous open\n"
1351
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_input: simultaneous open\n"
1353
; We have received a syn but no ACK, so we are having a simultaneous open..
1352
; We have received a syn but no ACK, so we are having a simultaneous open..
1354
        mov     [ebx + TCP_SOCKET.t_state], TCPS_SYN_RECEIVED
1353
        mov     [ebx + TCP_SOCKET.t_state], TCPS_SYN_RECEIVED
1355
 
1354
 
1356
;-------------------------------------
1355
;-------------------------------------
1357
; Common processing for receipt of SYN
1356
; Common processing for receipt of SYN
1358
 
1357
 
1359
  .trim:
1358
  .trim:
1360
        inc     [edx + TCP_header.SequenceNumber]
1359
        inc     [edx + TCP_header.SequenceNumber]
1361
 
1360
 
1362
; Drop any received data that doesnt fit in the receive window.
1361
; Drop any received data that doesnt fit in the receive window.
1363
        cmp     ecx, [ebx + TCP_SOCKET.RCV_WND]
1362
        cmp     ecx, [ebx + TCP_SOCKET.RCV_WND]
1364
        jbe     .dont_trim
1363
        jbe     .dont_trim
1365
 
1364
 
1366
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_input: received data does not fit in window, trimming %u bytes\n", eax
1365
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_input: received data does not fit in window, trimming %u bytes\n", eax
1367
        mov     ecx, [ebx + TCP_SOCKET.RCV_WND]
1366
        mov     ecx, [ebx + TCP_SOCKET.RCV_WND]
1368
        and     [edx + TCP_header.Flags], not (TH_FIN)
1367
        and     [edx + TCP_header.Flags], not (TH_FIN)
1369
;;; TODO: update stats
1368
;;; TODO: update stats
1370
 
1369
 
1371
  .dont_trim:
1370
  .dont_trim:
1372
        mov     eax, [edx + TCP_header.SequenceNumber]
1371
        mov     eax, [edx + TCP_header.SequenceNumber]
1373
        mov     [ebx + TCP_SOCKET.RCV_UP], eax
1372
        mov     [ebx + TCP_SOCKET.RCV_UP], eax
1374
        dec     eax
1373
        dec     eax
1375
        mov     [ebx + TCP_SOCKET.SND_WL1], eax
1374
        mov     [ebx + TCP_SOCKET.SND_WL1], eax
1376
 
1375
 
1377
  .ack_processed:
1376
  .ack_processed:
1378
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_input: ACK processed\n"
1377
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_input: ACK processed\n"
1379
 
1378
 
1380
;----------------------------------------------
1379
;----------------------------------------------
1381
; check if we need to update window information
1380
; check if we need to update window information
1382
 
1381
 
1383
        test    [edx + TCP_header.Flags], TH_ACK
1382
        test    [edx + TCP_header.Flags], TH_ACK
1384
        jz      .no_window_update
1383
        jz      .no_window_update
1385
 
1384
 
1386
        mov     eax, [ebx + TCP_SOCKET.SND_WL1]
1385
        mov     eax, [ebx + TCP_SOCKET.SND_WL1]
1387
        cmp     eax, [edx + TCP_header.SequenceNumber]
1386
        cmp     eax, [edx + TCP_header.SequenceNumber]
1388
        jb      .update_window
1387
        jb      .update_window
1389
        ja      @f
1388
        ja      @f
1390
 
1389
 
1391
        mov     eax, [ebx + TCP_SOCKET.SND_WL2]
1390
        mov     eax, [ebx + TCP_SOCKET.SND_WL2]
1392
        cmp     eax, [edx + TCP_header.AckNumber]
1391
        cmp     eax, [edx + TCP_header.AckNumber]
1393
        jb      .update_window
1392
        jb      .update_window
1394
        ja      .no_window_update
1393
        ja      .no_window_update
1395
       @@:
1394
       @@:
1396
 
1395
 
1397
        mov     eax, dword [edx + TCP_header.Window]
1396
        mov     eax, dword [edx + TCP_header.Window]
1398
        cmp     eax, [ebx + TCP_SOCKET.SND_WND]
1397
        cmp     eax, [ebx + TCP_SOCKET.SND_WND]
1399
        jbe     .no_window_update
1398
        jbe     .no_window_update
1400
 
1399
 
1401
  .update_window:
1400
  .update_window:
1402
 
1401
 
1403
;;; TODO: update stats (Keep track of pure window updates)
1402
;;; TODO: update stats (Keep track of pure window updates)
1404
 
1403
 
1405
        mov     eax, dword [edx + TCP_header.Window]
1404
        mov     eax, dword [edx + TCP_header.Window]
1406
        cmp     eax, [ebx + TCP_SOCKET.max_sndwnd]
1405
        cmp     eax, [ebx + TCP_SOCKET.max_sndwnd]
1407
        jbe     @f
1406
        jbe     @f
1408
        mov     [ebx + TCP_SOCKET.max_sndwnd], eax
1407
        mov     [ebx + TCP_SOCKET.max_sndwnd], eax
1409
       @@:
1408
       @@:
1410
        mov     [ebx + TCP_SOCKET.SND_WND], eax
1409
        mov     [ebx + TCP_SOCKET.SND_WND], eax
1411
 
1410
 
1412
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_input: Updating window to %u\n", eax
1411
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_input: Updating window to %u\n", eax
1413
 
1412
 
1414
        push    [edx + TCP_header.SequenceNumber]
1413
        push    [edx + TCP_header.SequenceNumber]
1415
        pop     [ebx + TCP_SOCKET.SND_WL1]
1414
        pop     [ebx + TCP_SOCKET.SND_WL1]
1416
 
1415
 
1417
        push    [edx + TCP_header.AckNumber]
1416
        push    [edx + TCP_header.AckNumber]
1418
        pop     [ebx + TCP_SOCKET.SND_WL2]
1417
        pop     [ebx + TCP_SOCKET.SND_WL2]
1419
 
1418
 
1420
        or      [temp_bits], TCP_BIT_NEEDOUTPUT
1419
        or      [temp_bits], TCP_BIT_NEEDOUTPUT
1421
 
1420
 
1422
  .no_window_update:
1421
  .no_window_update:
1423
 
1422
 
1424
;-----------------
1423
;-----------------
1425
; process URG flag
1424
; process URG flag
1426
 
1425
 
1427
        test    [edx + TCP_header.Flags], TH_URG
1426
        test    [edx + TCP_header.Flags], TH_URG
1428
        jz      .not_urgent
1427
        jz      .not_urgent
1429
 
1428
 
1430
        cmp     [edx + TCP_header.UrgentPointer], 0
1429
        cmp     [edx + TCP_header.UrgentPointer], 0
1431
        jz      .not_urgent
1430
        jz      .not_urgent
1432
 
1431
 
1433
        cmp     [ebx + TCP_SOCKET.t_state], TCPS_TIMED_WAIT
1432
        cmp     [ebx + TCP_SOCKET.t_state], TCPS_TIMED_WAIT
1434
        je      .not_urgent
1433
        je      .not_urgent
1435
 
1434
 
1436
; Ignore bogus urgent offsets
1435
; Ignore bogus urgent offsets
1437
 
1436
 
1438
        movzx   eax, [edx + TCP_header.UrgentPointer]
1437
        movzx   eax, [edx + TCP_header.UrgentPointer]
1439
        add     eax, [ebx + STREAM_SOCKET.rcv.size]
1438
        add     eax, [ebx + STREAM_SOCKET.rcv.size]
1440
        cmp     eax, SOCKET_MAXDATA
1439
        cmp     eax, SOCKET_MAXDATA
1441
        jbe     .not_urgent
1440
        jbe     .not_urgent
1442
 
1441
 
1443
        mov     [edx + TCP_header.UrgentPointer], 0
1442
        mov     [edx + TCP_header.UrgentPointer], 0
1444
        and     [edx + TCP_header.Flags], not (TH_URG)
1443
        and     [edx + TCP_header.Flags], not (TH_URG)
1445
        jmp     .do_data
1444
        jmp     .do_data
1446
 
1445
 
1447
  .not_urgent:
1446
  .not_urgent:
1448
 
1447
 
1449
; processing of received urgent pointer
1448
; processing of received urgent pointer
1450
 
1449
 
1451
        ;;; TODO (1051-1093)
1450
        ;;; TODO (1051-1093)
1452
 
1451
 
1453
 
1452
 
1454
;---------------------------------------
1453
;---------------------------------------
1455
; process the data in the segment (1094)
1454
; process the data in the segment (1094)
1456
 
1455
 
1457
  .do_data:
1456
  .do_data:
1458
 
1457
 
1459
        cmp     [ebx + TCP_SOCKET.t_state], TCPS_TIMED_WAIT
1458
        cmp     [ebx + TCP_SOCKET.t_state], TCPS_TIMED_WAIT
1460
        jae     .final_processing
1459
        jae     .final_processing
1461
 
1460
 
1462
        test    [edx + TCP_header.Flags], TH_FIN
1461
        test    [edx + TCP_header.Flags], TH_FIN
1463
        jnz     @f
1462
        jnz     @f
1464
 
1463
 
1465
        test    ecx, ecx
1464
        test    ecx, ecx
1466
        jz      .final_processing
1465
        jz      .final_processing
1467
       @@:
1466
       @@:
1468
 
1467
 
1469
; The segment is in order?
1468
; The segment is in order?
1470
        mov     eax, [edx + TCP_header.SequenceNumber]
1469
        mov     eax, [edx + TCP_header.SequenceNumber]
1471
        cmp     eax, [ebx + TCP_SOCKET.RCV_NXT]
1470
        cmp     eax, [ebx + TCP_SOCKET.RCV_NXT]
1472
        jne     .out_of_order
1471
        jne     .out_of_order
1473
 
1472
 
1474
; The reassembly queue is empty?
1473
; The reassembly queue is empty?
1475
        cmp     [ebx + TCP_SOCKET.seg_next], 0
1474
        cmp     [ebx + TCP_SOCKET.seg_next], 0
1476
        jne     .out_of_order
1475
        jne     .out_of_order
1477
 
1476
 
1478
; The connection is established?
1477
; The connection is established?
1479
        cmp     [ebx + TCP_SOCKET.t_state], TCPS_ESTABLISHED
1478
        cmp     [ebx + TCP_SOCKET.t_state], TCPS_ESTABLISHED
1480
        jne     .out_of_order
1479
        jne     .out_of_order
1481
 
1480
 
1482
; Ok, lets do this..  Set delayed ACK flag and copy data into socket buffer
1481
; Ok, lets do this..  Set delayed ACK flag and copy data into socket buffer
1483
        or      [ebx + TCP_SOCKET.t_flags], TF_DELACK
1482
        or      [ebx + TCP_SOCKET.t_flags], TF_DELACK
1484
 
1483
 
1485
        pusha
1484
        pusha
1486
        mov     esi, [dataoffset]
1485
        mov     esi, [dataoffset]
1487
        add     esi, edx
1486
        add     esi, edx
1488
        lea     eax, [ebx + STREAM_SOCKET.rcv]
1487
        lea     eax, [ebx + STREAM_SOCKET.rcv]
1489
        call    SOCKET_ring_write                       ; Add the data to the socket buffer
1488
        call    SOCKET_ring_write                       ; Add the data to the socket buffer
1490
        add     [ebx + TCP_SOCKET.RCV_NXT], ecx         ; Update sequence number with number of bytes we have copied
1489
        add     [ebx + TCP_SOCKET.RCV_NXT], ecx         ; Update sequence number with number of bytes we have copied
1491
        popa
1490
        popa
1492
 
1491
 
1493
; Wake up the sleeping process
1492
; Wake up the sleeping process
1494
        mov     eax, ebx
1493
        mov     eax, ebx
1495
        call    SOCKET_notify
1494
        call    SOCKET_notify
1496
 
1495
 
1497
        jmp     .data_done
1496
        jmp     .data_done
1498
 
1497
 
1499
  .out_of_order:
1498
  .out_of_order:
1500
        DEBUGF  DEBUG_NETWORK_VERBOSE,  "TCP data is out of order!\nSequencenumber is %u, we expected %u.\n", \
1499
        DEBUGF  DEBUG_NETWORK_VERBOSE,  "TCP data is out of order!\nSequencenumber is %u, we expected %u.\n", \
1501
        [edx + TCP_header.SequenceNumber], [ebx + TCP_SOCKET.RCV_NXT]
1500
        [edx + TCP_header.SequenceNumber], [ebx + TCP_SOCKET.RCV_NXT]
1502
 
1501
 
1503
; Uh-oh, some data is out of order, lets call TCP reassemble for help
1502
; Uh-oh, some data is out of order, lets call TCP reassemble for help
1504
 
1503
 
1505
        call    TCP_reassemble
1504
        call    TCP_reassemble
1506
 
1505
 
1507
; Generate ACK immediately, to let the other end know that a segment was received out of order,
1506
; Generate ACK immediately, to let the other end know that a segment was received out of order,
1508
; and to tell it what sequence number is expected. This aids the fast-retransmit algorithm.
1507
; and to tell it what sequence number is expected. This aids the fast-retransmit algorithm.
1509
        or      [ebx + TCP_SOCKET.t_flags], TF_ACKNOW
1508
        or      [ebx + TCP_SOCKET.t_flags], TF_ACKNOW
1510
  .data_done:
1509
  .data_done:
1511
 
1510
 
1512
;---------------
1511
;---------------
1513
; FIN processing
1512
; FIN processing
1514
 
1513
 
1515
        test    [edx + TCP_header.Flags], TH_FIN
1514
        test    [edx + TCP_header.Flags], TH_FIN
1516
        jz      .final_processing
1515
        jz      .final_processing
1517
 
1516
 
1518
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_input: Processing FIN\n"
1517
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_input: Processing FIN\n"
1519
 
1518
 
1520
        cmp     [ebx + TCP_SOCKET.t_state], TCPS_TIMED_WAIT
1519
        cmp     [ebx + TCP_SOCKET.t_state], TCPS_TIMED_WAIT
1521
        jae     .not_first_fin
1520
        jae     .not_first_fin
1522
 
1521
 
1523
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_input: First FIN for this connection\n"
1522
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_input: First FIN for this connection\n"
1524
 
1523
 
1525
        mov     eax, ebx
1524
        mov     eax, ebx
1526
        call    SOCKET_cant_recv_more
1525
        call    SOCKET_cant_recv_more
1527
 
1526
 
1528
        or      [ebx + TCP_SOCKET.t_flags], TF_ACKNOW
1527
        or      [ebx + TCP_SOCKET.t_flags], TF_ACKNOW
1529
        inc     [ebx + TCP_SOCKET.RCV_NXT]
1528
        inc     [ebx + TCP_SOCKET.RCV_NXT]
1530
 
1529
 
1531
  .not_first_fin:
1530
  .not_first_fin:
1532
        mov     eax, [ebx + TCP_SOCKET.t_state]
1531
        mov     eax, [ebx + TCP_SOCKET.t_state]
1533
        shl     eax, 2
1532
        shl     eax, 2
1534
        jmp     dword [eax + .FIN_sw_list]
1533
        jmp     dword [eax + .FIN_sw_list]
1535
 
1534
 
1536
  .FIN_sw_list:
1535
  .FIN_sw_list:
1537
        dd      .final_processing       ; TCPS_CLOSED
1536
        dd      .final_processing       ; TCPS_CLOSED
1538
        dd      .final_processing       ; TCPS_LISTEN
1537
        dd      .final_processing       ; TCPS_LISTEN
1539
        dd      .final_processing       ; TCPS_SYN_SENT
1538
        dd      .final_processing       ; TCPS_SYN_SENT
1540
        dd      .fin_syn_est            ; TCPS_SYN_RECEIVED
1539
        dd      .fin_syn_est            ; TCPS_SYN_RECEIVED
1541
        dd      .fin_syn_est            ; TCPS_ESTABLISHED
1540
        dd      .fin_syn_est            ; TCPS_ESTABLISHED
1542
        dd      .final_processing       ; TCPS_CLOSE_WAIT
1541
        dd      .final_processing       ; TCPS_CLOSE_WAIT
1543
        dd      .fin_wait1              ; TCPS_FIN_WAIT_1
1542
        dd      .fin_wait1              ; TCPS_FIN_WAIT_1
1544
        dd      .final_processing       ; TCPS_CLOSING
1543
        dd      .final_processing       ; TCPS_CLOSING
1545
        dd      .final_processing       ; TCPS_LAST_ACK
1544
        dd      .final_processing       ; TCPS_LAST_ACK
1546
        dd      .fin_wait2              ; TCPS_FIN_WAIT_2
1545
        dd      .fin_wait2              ; TCPS_FIN_WAIT_2
1547
        dd      .fin_timed              ; TCPS_TIMED_WAIT
1546
        dd      .fin_timed              ; TCPS_TIMED_WAIT
1548
 
1547
 
1549
  .fin_syn_est:
1548
  .fin_syn_est:
1550
        mov     [ebx + TCP_SOCKET.t_state], TCPS_CLOSE_WAIT
1549
        mov     [ebx + TCP_SOCKET.t_state], TCPS_CLOSE_WAIT
1551
        jmp     .final_processing
1550
        jmp     .final_processing
1552
 
1551
 
1553
  .fin_wait1:
1552
  .fin_wait1:
1554
        mov     [ebx + TCP_SOCKET.t_state], TCPS_CLOSING
1553
        mov     [ebx + TCP_SOCKET.t_state], TCPS_CLOSING
1555
        jmp     .final_processing
1554
        jmp     .final_processing
1556
 
1555
 
1557
  .fin_wait2:
1556
  .fin_wait2:
1558
        mov     [ebx + TCP_SOCKET.t_state], TCPS_TIMED_WAIT
1557
        mov     [ebx + TCP_SOCKET.t_state], TCPS_TIMED_WAIT
1559
        mov     eax, ebx
1558
        mov     eax, ebx
1560
        call    TCP_cancel_timers
1559
        call    TCP_cancel_timers
1561
        call    SOCKET_is_disconnected
1560
        call    SOCKET_is_disconnected
1562
 
1561
 
1563
  .fin_timed:
1562
  .fin_timed:
1564
        mov     [ebx + TCP_SOCKET.timer_timed_wait], 2 * TCP_time_MSL
1563
        mov     [ebx + TCP_SOCKET.timer_timed_wait], 2 * TCP_time_MSL
1565
        or      [ebx + TCP_SOCKET.timer_flags], timer_flag_wait
1564
        or      [ebx + TCP_SOCKET.timer_flags], timer_flag_wait
1566
 
1565
 
1567
;-----------------
1566
;-----------------
1568
; Final processing
1567
; Final processing
1569
 
1568
 
1570
  .final_processing:
1569
  .final_processing:
1571
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_input: Final processing\n"
1570
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_input: Final processing\n"
1572
 
1571
 
1573
        push    ebx
1572
        push    ebx
1574
        lea     ecx, [ebx + SOCKET.mutex]
1573
        lea     ecx, [ebx + SOCKET.mutex]
1575
        call    mutex_unlock
1574
        call    mutex_unlock
1576
        pop     eax
1575
        pop     eax
1577
 
1576
 
1578
        test    [temp_bits], TCP_BIT_NEEDOUTPUT
1577
        test    [temp_bits], TCP_BIT_NEEDOUTPUT
1579
        jnz     .need_output
1578
        jnz     .need_output
1580
 
1579
 
1581
        test    [eax + TCP_SOCKET.t_flags], TF_ACKNOW
1580
        test    [eax + TCP_SOCKET.t_flags], TF_ACKNOW
1582
        jz      .done
1581
        jz      .done
1583
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_input: ACK now!\n"
1582
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_input: ACK now!\n"
1584
 
1583
 
1585
  .need_output:
1584
  .need_output:
1586
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_input: need output\n"
1585
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_input: need output\n"
1587
        call    TCP_output
1586
        call    TCP_output
1588
 
1587
 
1589
  .done:
1588
  .done:
1590
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_input: dumping\n"
1589
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_input: dumping\n"
1591
 
1590
 
1592
        call    NET_BUFF_free
1591
        call    NET_BUFF_free
1593
        jmp     .loop
1592
        jmp     .loop
1594
 
1593
 
1595
 
1594
 
1596
;-----------------
1595
;-----------------
1597
; Drop the segment
1596
; Drop the segment
1598
 
1597
 
1599
 
1598
 
1600
  .drop_after_ack:
1599
  .drop_after_ack:
1601
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_input: Drop after ACK\n"
1600
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_input: Drop after ACK\n"
1602
 
1601
 
1603
        push    edx ebx
1602
        push    edx ebx
1604
        lea     ecx, [ebx + SOCKET.mutex]
1603
        lea     ecx, [ebx + SOCKET.mutex]
1605
        call    mutex_unlock
1604
        call    mutex_unlock
1606
        pop     eax edx
1605
        pop     eax edx
1607
 
1606
 
1608
        test    [edx + TCP_header.Flags], TH_RST
1607
        test    [edx + TCP_header.Flags], TH_RST
1609
        jnz     .done
1608
        jnz     .done
1610
 
1609
 
1611
        or      [eax + TCP_SOCKET.t_flags], TF_ACKNOW
1610
        or      [eax + TCP_SOCKET.t_flags], TF_ACKNOW
1612
        jmp     .need_output
1611
        jmp     .need_output
1613
 
1612
 
1614
  .drop_with_reset:
1613
  .drop_with_reset:
1615
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_input: Drop with reset\n"
1614
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_input: Drop with reset\n"
1616
 
1615
 
1617
        push    ebx edx
1616
        push    ebx edx
1618
        lea     ecx, [ebx + SOCKET.mutex]
1617
        lea     ecx, [ebx + SOCKET.mutex]
1619
        call    mutex_unlock
1618
        call    mutex_unlock
1620
        pop     edx ebx
1619
        pop     edx ebx
1621
 
1620
 
1622
        test    [edx + TCP_header.Flags], TH_RST
1621
        test    [edx + TCP_header.Flags], TH_RST
1623
        jnz     .done
1622
        jnz     .done
1624
 
1623
 
1625
        ;;; if its a multicast/broadcast, also drop
1624
        ;;; if its a multicast/broadcast, also drop
1626
 
1625
 
1627
        test    [edx + TCP_header.Flags], TH_ACK
1626
        test    [edx + TCP_header.Flags], TH_ACK
1628
        jnz     .respond_ack
1627
        jnz     .respond_ack
1629
 
1628
 
1630
        test    [edx + TCP_header.Flags], TH_SYN
1629
        test    [edx + TCP_header.Flags], TH_SYN
1631
        jnz     .respond_syn
1630
        jnz     .respond_syn
1632
        jmp     .done
1631
        jmp     .done
1633
 
1632
 
1634
;---------
1633
;---------
1635
; Respond
1634
; Respond
1636
 
1635
 
1637
  .respond_ack:
1636
  .respond_ack:
1638
        push    ebx
1637
        push    ebx
1639
        mov     cl, TH_RST
1638
        mov     cl, TH_RST
1640
        call    TCP_respond
1639
        call    TCP_respond
1641
        pop     ebx
1640
        pop     ebx
1642
        jmp     .destroy_new_socket
1641
        jmp     .destroy_new_socket
1643
 
1642
 
1644
  .respond_syn:
1643
  .respond_syn:
1645
        push    ebx
1644
        push    ebx
1646
        mov     cl, TH_RST + TH_ACK
1645
        mov     cl, TH_RST + TH_ACK
1647
        call    TCP_respond
1646
        call    TCP_respond
1648
        pop     ebx
1647
        pop     ebx
1649
        jmp     .destroy_new_socket
1648
        jmp     .destroy_new_socket
1650
 
1649
 
1651
;-----------------------------------------
1650
;-----------------------------------------
1652
; The connection has no associated socket
1651
; The connection has no associated socket
1653
 
1652
 
1654
  .no_socket:
1653
  .no_socket:
1655
        pusha
1654
        pusha
1656
        mov     ecx, socket_mutex
1655
        mov     ecx, socket_mutex
1657
        call    mutex_unlock
1656
        call    mutex_unlock
1658
        popa
1657
        popa
1659
 
1658
 
1660
  .respond_seg_reset:
1659
  .respond_seg_reset:
1661
        test    [edx + TCP_header.Flags], TH_RST
1660
        test    [edx + TCP_header.Flags], TH_RST
1662
        jnz     .drop_no_socket
1661
        jnz     .drop_no_socket
1663
 
1662
 
1664
        ;;; TODO: if its a multicast/broadcast, also drop
1663
        ;;; TODO: if its a multicast/broadcast, also drop
1665
 
1664
 
1666
        test    [edx + TCP_header.Flags], TH_ACK
1665
        test    [edx + TCP_header.Flags], TH_ACK
1667
        jnz     .respond_seg_ack
1666
        jnz     .respond_seg_ack
1668
 
1667
 
1669
        test    [edx + TCP_header.Flags], TH_SYN
1668
        test    [edx + TCP_header.Flags], TH_SYN
1670
        jnz     .respond_seg_syn
1669
        jnz     .respond_seg_syn
1671
 
1670
 
1672
        jmp     .drop_no_socket
1671
        jmp     .drop_no_socket
1673
 
1672
 
1674
  .respond_seg_ack:
1673
  .respond_seg_ack:
1675
        mov     cl, TH_RST
1674
        mov     cl, TH_RST
-
 
1675
        xor     ebx, ebx                ; FIXME: find a way to get the receiving device ptr
1676
        call    TCP_respond_segment
1676
        call    TCP_respond_segment
1677
        jmp     .drop_no_socket
1677
        jmp     .drop_no_socket
1678
 
1678
 
1679
  .respond_seg_syn:
1679
  .respond_seg_syn:
1680
        mov     cl, TH_RST + TH_ACK
1680
        mov     cl, TH_RST + TH_ACK
-
 
1681
        xor     ebx, ebx                ; FIXME: find a way to get the receiving device ptr
1681
        call    TCP_respond_segment
1682
        call    TCP_respond_segment
1682
        jmp     .drop_no_socket
1683
        jmp     .drop_no_socket
1683
 
1684
 
1684
;------------------------------------------------
1685
;------------------------------------------------
1685
; Unlock socket mutex and prepare to drop segment
1686
; Unlock socket mutex and prepare to drop segment
1686
 
1687
 
1687
  .drop:
1688
  .drop:
1688
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_input: Dropping segment\n"
1689
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_input: Dropping segment\n"
1689
 
1690
 
1690
        pusha
1691
        pusha
1691
        lea     ecx, [ebx + SOCKET.mutex]
1692
        lea     ecx, [ebx + SOCKET.mutex]
1692
        call    mutex_unlock
1693
        call    mutex_unlock
1693
        popa
1694
        popa
1694
 
1695
 
1695
;--------------------------------------------
1696
;--------------------------------------------
1696
; Destroy the newly created socket if needed
1697
; Destroy the newly created socket if needed
1697
 
1698
 
1698
  .destroy_new_socket:
1699
  .destroy_new_socket:
1699
        test    [temp_bits], TCP_BIT_DROPSOCKET
1700
        test    [temp_bits], TCP_BIT_DROPSOCKET
1700
        jz      .drop_no_socket
1701
        jz      .drop_no_socket
1701
 
1702
 
1702
        mov     eax, ebx
1703
        mov     eax, ebx
1703
        call    SOCKET_free
1704
        call    SOCKET_free
1704
 
1705
 
1705
;------------------
1706
;------------------
1706
; Drop the segment
1707
; Drop the segment
1707
 
1708
 
1708
  .drop_no_socket:
1709
  .drop_no_socket:
1709
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_input: Drop (no socket)\n"
1710
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_input: Drop (no socket)\n"
1710
 
1711
 
1711
        call    NET_BUFF_free
1712
        call    NET_BUFF_free
1712
        jmp     .loop
1713
        jmp     .loop
1713
 
1714
 
1714
endp
1715
endp
1715
>
1716
>
1716
>
1717
>
1717
>
1718
>
1718
>
1719
>