Subversion Repositories Kolibri OS

Rev

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

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