Subversion Repositories Kolibri OS

Rev

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

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