Subversion Repositories Kolibri OS

Rev

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

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