Subversion Repositories Kolibri OS

Rev

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

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