Subversion Repositories Kolibri OS

Rev

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

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