From b90d3b7f561e9a3f32e1d58ad05bd293df01e198 Mon Sep 17 00:00:00 2001 From: hidnplayr Date: Wed, 28 Jul 2010 23:59:42 +0000 Subject: [PATCH] Updates in TCP code of net branch git-svn-id: svn://kolibrios.org@1533 a494cfbc-eb01-0410-851d-a64ba20cac60 --- kernel/branches/net/network/ARP.inc | 10 +- kernel/branches/net/network/socket.inc | 247 ++++++++++++------------ kernel/branches/net/network/tcp.inc | 250 ++++++++++++++++--------- 3 files changed, 288 insertions(+), 219 deletions(-) diff --git a/kernel/branches/net/network/ARP.inc b/kernel/branches/net/network/ARP.inc index a4bb401444..a18468b9e6 100644 --- a/kernel/branches/net/network/ARP.inc +++ b/kernel/branches/net/network/ARP.inc @@ -506,16 +506,18 @@ ARP_IP_to_MAC: ;; TODO: check if driver could transmit packet - pop eax - imul eax, ARP_ENTRY.size - add eax, ARP_table + pop esi + imul esi, ARP_ENTRY.size + add esi, ARP_table mov ecx, 25 .wait_loop: - cmp [eax + ARP_ENTRY.Status], 1 + cmp [esi + ARP_ENTRY.Status], 1 je .got_it + push esi mov esi, 10 call delay_ms + pop esi loop .wait_loop mov eax, -2 ; request send diff --git a/kernel/branches/net/network/socket.inc b/kernel/branches/net/network/socket.inc index 758f9b31ee..4febc150ec 100644 --- a/kernel/branches/net/network/socket.inc +++ b/kernel/branches/net/network/socket.inc @@ -169,6 +169,7 @@ struc RING_BUFFER { .read_ptr dd ? ; Read pointer .write_ptr dd ? ; Write pointer .size dd ? ; Number of bytes buffered + .end: } virtual at 0 @@ -179,10 +180,9 @@ end virtual virtual at TCP_SOCKET.end - rcv RING_BUFFER - snd RING_BUFFER - STREAM_SOCKET: + .rcv rd RING_BUFFER.end/4 + .snd rd RING_BUFFER.end/4 .end: end virtual @@ -221,21 +221,12 @@ macro SOCKET_init { mov ecx, 4 rep stosd -;--- for random port -- - - mov al, 0x0 ; set up 1s timer - out 0x70, al - in al, 0x71 - -;---------------------- - @@: pseudo_random eax cmp ax, MIN_EPHEMERAL_PORT jl @r cmp ax, MAX_EPHEMERAL_PORT jg @r - mov [last_UDP_port], ax @@: @@ -244,7 +235,6 @@ macro SOCKET_init { jl @r cmp ax, MAX_EPHEMERAL_PORT jg @r - mov [last_TCP_port], ax } @@ -318,22 +308,13 @@ SOCKET_open: cmp edx, IP_PROTO_TCP jnz .no_stream - mov esi, eax - stdcall kernel_alloc, SOCKET_MAXDATA - mov [esi + rcv.start_ptr], eax - mov [esi + rcv.write_ptr], eax - mov [esi + rcv.read_ptr], eax - mov [esi + rcv.size], 0 - add eax, SOCKET_MAXDATA - mov [esi + rcv.end_ptr], eax + mov ebx, eax - stdcall kernel_alloc, SOCKET_MAXDATA - mov [esi + snd.start_ptr], eax - mov [esi + snd.write_ptr], eax - mov [esi + snd.read_ptr], eax - mov [esi + snd.size], 0 - add eax, SOCKET_MAXDATA - mov [esi + snd.end_ptr], eax + lea eax, [ebx + STREAM_SOCKET.snd] + call SOCKET_ring_create + + lea eax, [ebx + STREAM_SOCKET.rcv] + call SOCKET_ring_create ret @@ -497,9 +478,11 @@ SOCKET_connect: mov ebx, [TCP_sequence_num] add [TCP_sequence_num], 6400 mov [eax + TCP_SOCKET.ISS], ebx - mov [eax + TCP_SOCKET.timer_keepalive], 120 ; 120*640ms => 75,6 seconds + mov [eax + TCP_SOCKET.timer_keepalive], TCP_time_keep_init -;;;; mov [ebx + TCP_SOCKET.timer_retransmission], + TCP_sendseqinit eax + +;;;; mov [ebx + TCP_SOCKET.timer_retransmission], ;; todo: create macro to set retransmission timer push eax call TCP_output @@ -671,6 +654,9 @@ SOCKET_receive: call SOCKET_num_to_ptr jz s_error + cmp [eax + SOCKET.Type], IP_PROTO_TCP ;;;;;;;; + je .tcp + mov ebx, esi get_from_queue (eax + SOCKET_QUEUE_LOCATION),\ SOCKET_QUEUE_SIZE,\ @@ -707,9 +693,17 @@ SOCKET_receive: .nd: ; remove the packet ;;; TODO: only if it is empty!! -;;;; call TCP_output ; only if it is tcp - call kernel_free + ret + + .tcp: + + mov ecx, esi + mov edi, edx + add eax, STREAM_SOCKET.rcv + call SOCKET_ring_read + + mov dword[esp+32], ecx ; return number of bytes copied in ebx ret @@ -787,8 +781,13 @@ SOCKET_send: jz s_error @@: -;;;; TODO: queue the data + push eax + mov ecx, esi + mov esi, edx + add eax, STREAM_SOCKET.snd + call SOCKET_ring_write + pop eax call TCP_output mov [esp+32], eax @@ -1028,58 +1027,86 @@ SOCKET_input: ret + +;-------------------------- +; +; eax = ptr to ring struct (just a buffer of the right size) +; +align 4 +SOCKET_ring_create: + + mov esi, eax + stdcall create_ring_buffer, SOCKET_MAXDATA, PG_SW + + DEBUGF 1,"SOCKET_ring_created: %x\n", eax + mov [esi + RING_BUFFER.start_ptr], eax + mov [esi + RING_BUFFER.write_ptr], eax + mov [esi + RING_BUFFER.read_ptr], eax + mov [esi + RING_BUFFER.size], 0 + add eax, SOCKET_MAXDATA + mov [esi + RING_BUFFER.end_ptr], eax + + ret + ;----------------------------------------------------------------- ; -; SOCKET_ring_add +; SOCKET_ring_write ; -; Adds data to a stream socket +; Adds data to a stream socket, and updates write pointer and size ; ; IN: eax = ptr to ring struct ; ecx = data size ; esi = ptr to data ; -; OUT: eax = number of bytes stored +; OUT: ecx = number of bytes stored ; ;----------------------------------------------------------------- align 4 -SOCKET_ring_add: +SOCKET_ring_write: - DEBUGF 1,"SOCKET_ring_add: ringbuff=%x ptr=%x size=%u\n", eax, esi, ecx + DEBUGF 1,"SOCKET_ring_write: ringbuff=%x ptr=%x size=%u\n", eax, esi, ecx - mov edi, [eax + RING_BUFFER.size] - add edi, ecx - cmp edi, SOCKET_MAXDATA + add [eax + RING_BUFFER.size], ecx + cmp [eax + RING_BUFFER.size], SOCKET_MAXDATA jg .too_large - mov [eax + RING_BUFFER.size], edi ; update size .copy: - push ecx ;<<<< 1 - mov edi, [eax + RING_BUFFER.write_ptr] ; set write ptr in edi - add [eax + RING_BUFFER.write_ptr], ecx ; update write pointer - mov edx, [eax + RING_BUFFER.end_ptr] - cmp edx, [eax + RING_BUFFER.write_ptr] - jg .copy_in_2 - je .wrap_write_ptr + mov edi, [eax + RING_BUFFER.write_ptr] + DEBUGF 2,"Copying %u bytes from %x to %x\n", ecx, esi, edi - .copy_more: push ecx - and ecx, 3 - rep movsb - pop ecx - shr ecx, 2 + shr ecx, 1 + jnc .nb + movsb +.nb: + shr ecx, 1 + jnc .nw + movsw +.nw: + test ecx, ecx + jz .nd rep movsd - pop ecx ; >>>> 1/2 - DEBUGF 2,"Copied %u bytes\n", ecx +.nd: + pop ecx + + cmp edi, [eax + RING_BUFFER.end_ptr] + jge .wrap + mov [eax + RING_BUFFER.write_ptr], edi + + ret + + .wrap: + sub edi, SOCKET_MAXDATA + mov [eax + RING_BUFFER.write_ptr], edi ret .too_large: mov ecx, SOCKET_MAXDATA ; calculate number of bytes available in buffer sub ecx, [eax + RING_BUFFER.size] - jz .full + jge .full mov [eax + RING_BUFFER.size], SOCKET_MAXDATA ; update size, we will fill buffer completely - jmp .copy .full: @@ -1087,87 +1114,56 @@ SOCKET_ring_add: xor ecx, ecx ret - .copy_in_2: - DEBUGF 1,"Copying in 2 passes\n" - - mov edx, ecx - mov ecx, [eax + RING_BUFFER.end_ptr] ; find number of bytes till end of buffer - sub ecx, edi - sub edx, ecx - push edx ; <<<< 2 - - mov edi, [eax + RING_BUFFER.start_ptr] - call .copy_more - - .wrap_write_ptr: - sub [eax + RING_BUFFER.write_ptr], SOCKET_MAXDATA ; update write pointer - jmp .copy_more - - - ;----------------------------------------------------------------- ; ; SOCKET_ring_read ; -; reads the data, but let the data remain in the buffer +; reads the data, BUT DOES NOT CLEAR IT FROM MEMORY YET ; ; IN: eax = ptr to ring struct ; ecx = buffer size ; edi = ptr to buffer ; -; OUT: eax = number of bytes read +; OUT: ecx = number of bytes read ; ;----------------------------------------------------------------- align 4 SOCKET_ring_read: - DEBUGF 1,"SOCKET_ring_read: ringbuff=%x ptr=%x size=%u\n", eax, esi, ecx + DEBUGF 1,"SOCKET_ring_read: ringbuff=%x ptr=%x size=%u\n", eax, edi, ecx - cmp [eax + RING_BUFFER.size], ecx ; update size - jl .too_large + cmp ecx, [eax + RING_BUFFER.size] + jg .less_data - mov esi, [eax + RING_BUFFER.read_ptr] ; update read ptr .copy: - push ecx ;<<<< 1 - mov edx, [eax + RING_BUFFER.read_ptr] - add edx, ecx - cmp edx, [eax + RING_BUFFER.end_ptr] - jg .copy_in_2 + mov esi, [eax + RING_BUFFER.read_ptr] - .copy_more: + DEBUGF 2,"Copying %u bytes from %x to %x\n", ecx, esi, edi push ecx - and ecx, 3 - rep movsb - pop ecx - shr ecx, 2 + shr ecx, 1 + jnc .nb + movsb +.nb: + shr ecx, 1 + jnc .nw + movsw +.nw: + test ecx, ecx + jz .nd rep movsd - pop ecx ; >>>> 1/2 - DEBUGF 2,"Copied %u bytes\n", ecx +.nd: + pop ecx +; .no_data_at_all: ret - .too_large: + .less_data: mov ecx, [eax + RING_BUFFER.size] + test ecx, ecx +; jz .no_data_at_all jmp .copy - .full: - DEBUGF 2,"Ring buffer is full!\n" - xor ecx, ecx - ret - - .copy_in_2: - DEBUGF 1,"Copying in 2 passes\n" - - mov edx, ecx - mov ecx, [eax + RING_BUFFER.end_ptr] ; find number of bytes till end of buffer - sub ecx, edi - sub edx, ecx - push edx ; <<<< 2 - - mov esi, [eax + RING_BUFFER.start_ptr] - call .copy_more - ;----------------------------------------------------------------- ; @@ -1186,26 +1182,19 @@ SOCKET_ring_free: DEBUGF 1,"Trying to free %u bytes of data from ring %x\n", ecx, eax - cmp ecx, [eax + RING_BUFFER.size] - jle .go_for_it - - cmp ecx, SOCKET_MAXDATA ;;;; - jg .moron_input - - mov ecx, [eax + RING_BUFFER.size] - - .go_for_it: sub [eax + RING_BUFFER.size], ecx + jl .sumthinwong add [eax + RING_BUFFER.read_ptr], ecx mov edx, [eax + RING_BUFFER.end_ptr] cmp [eax + RING_BUFFER.read_ptr], edx jl @f - sub [eax + RING_BUFFER.read_ptr], SOCKET_MAXDATA ;;;;; + sub [eax + RING_BUFFER.read_ptr], SOCKET_MAXDATA @@: ret - .moron_input: + .sumthinwong: ; we could free all available bytes, but that would be stupid, i guess.. + add [eax + RING_BUFFER.size], ecx xor ecx, ecx ret @@ -1371,8 +1360,8 @@ SOCKET_free: cmp [eax + SOCKET.Type], IP_PROTO_TCP jnz .no_stream - stdcall kernel_free, [eax + rcv.start_ptr] - stdcall kernel_free, [eax + snd.start_ptr] + stdcall kernel_free, [eax + STREAM_SOCKET.rcv + RING_BUFFER.start_ptr] + stdcall kernel_free, [eax + STREAM_SOCKET.snd + RING_BUFFER.start_ptr] .no_stream: push eax ; this will be passed to kernel_free @@ -1400,9 +1389,9 @@ SOCKET_free: ret -; socket nr in ebx -; new socket nr in eax -; preserver edx +; IN: socket nr in ebx +; OUT: socket nr in eax +; preserves edx align 4 SOCKET_fork: @@ -1440,7 +1429,7 @@ SOCKET_fork: ; Get socket structure address by its number ; ; IN: ecx = socket number -; OUT: ecx = 0 on error, socket ptr otherwise +; OUT: eax = 0 on error, socket ptr otherwise ; ZF = set on error ; ;--------------------------------------------------- diff --git a/kernel/branches/net/network/tcp.inc b/kernel/branches/net/network/tcp.inc index f9cf617297..db2d8d817c 100644 --- a/kernel/branches/net/network/tcp.inc +++ b/kernel/branches/net/network/tcp.inc @@ -266,6 +266,30 @@ macro TCP_checksum IP1, IP2 { } ; returns in dx only +macro TCP_sendseqinit ptr { + + push edi ;;;; i dont like this static use of edi + mov edi, [ptr + TCP_SOCKET.ISS] + mov [ptr + TCP_SOCKET.SND_UP], edi + mov [ptr + TCP_SOCKET.SND_MAX], edi + mov [ptr + TCP_SOCKET.SND_NXT], edi + mov [ptr + TCP_SOCKET.SND_UNA], edi + pop edi + +} + +macro TCP_rcvseqinit ptr { + + push edi + mov edi, [ptr + TCP_SOCKET.IRS] + inc edi + mov [ptr + TCP_SOCKET.RCV_NXT], edi + mov [ptr + TCP_SOCKET.RCV_ADV], edi + pop edi + +} + + ;----------------------------------------------------------------- ; @@ -420,7 +444,7 @@ TCP_input: ;----------------------------------- ; Is this socket a listening socket? -; test [ebx + SOCKET.options], SO_ACCEPTCON + test [ebx + SOCKET.options], SO_ACCEPTCON ; jnz .listening_socket ;;;;; TODO ;------------------------------------- @@ -477,7 +501,7 @@ TCP_input: movzx eax, word[edi+2] rol ax, 8 - DEBUGF 1,"Maxseg: %u", ax + DEBUGF 1,"Maxseg: %u\n", ax mov [ebx + TCP_SOCKET.t_maxseg], eax @@ -493,7 +517,7 @@ TCP_input: test [edx + TCP_segment.Flags], TH_SYN jz @f - DEBUGF 1,"Got window option" + DEBUGF 1,"Got window option\n" ;;;;; @@: @@ -505,7 +529,7 @@ TCP_input: cmp byte [edi+1], 10 jne .no_options - DEBUGF 1,"Got timestamp option" + DEBUGF 1,"Got timestamp option\n" ;;;;; @@ -532,19 +556,29 @@ TCP_input: cmp [ebx + TCP_SOCKET.t_state], TCB_ESTABLISHED jnz .not_uni_xfer + DEBUGF 1,"1\n" + test [edx + TCP_segment.Flags], TH_SYN + TH_FIN + TH_RST + TH_URG jnz .not_uni_xfer + DEBUGF 1,"2\n" + test [edx + TCP_segment.Flags], TH_ACK jz .not_uni_xfer + DEBUGF 1,"3\n" + mov eax, [edx + TCP_segment.SequenceNumber] cmp eax, [ebx + TCP_SOCKET.RCV_NXT] jne .not_uni_xfer - movzx eax, [edx + TCP_segment.Window] ;;;;; (should use pre-calculated value isntead: todo: figure out where to store it) - cmp eax, [ebx + TCP_SOCKET.SND_WND] - jne .not_uni_xfer + DEBUGF 1,"4\n" + +;; movzx eax, [edx + TCP_segment.Window] ;;;;; (should use pre-calculated value isntead: todo: figure out where to store it) +;; cmp eax, [ebx + TCP_SOCKET.SND_WND] +;; jne .not_uni_xfer + + DEBUGF 1,"5\n" mov eax, [ebx + TCP_SOCKET.SND_NXT] cmp eax, [ebx + TCP_SOCKET.SND_MAX] @@ -584,7 +618,7 @@ TCP_input: ; Delete acknowledged bytes from send buffer ; notice how ecx already holds number of bytes ack-ed - lea eax, [ebx + snd] + lea eax, [ebx + STREAM_SOCKET.snd] call SOCKET_ring_free ; Stop retransmit timer @@ -620,8 +654,11 @@ TCP_input: DEBUGF 1,"header prediction: we are receiver\nreceiving %u bytes of data\n", ecx add esi, edx - lea eax, [ebx + rcv] - call SOCKET_ring_add ; Add the data to the socket buffer + lea eax, [ebx + STREAM_SOCKET.rcv] + call SOCKET_ring_write ; Add the data to the socket buffer + + mov eax, ebx + call SOCKET_notify_owner add [ebx + TCP_SOCKET.RCV_NXT], ecx ; Update sequence number with number of bytes we have copied or [ebx + TCP_SOCKET.t_flags], TF_DELACK ; Set delayed ack flag @@ -633,18 +670,13 @@ TCP_input: .not_uni_xfer: - DEBUGF 1,"Header prediction failed\n" + DEBUGF 1,"Header prediction failed\n" ; time to do it the "slow" way :) ;------------------------------ ; Calculate receive window size ;;;; -;------------------------- -; TCP slow input procedure - - DEBUGF 1,"TCP slow input procedure\n" - cmp [ebx + TCP_SOCKET.t_state], TCB_LISTEN je .LISTEN @@ -654,7 +686,7 @@ TCP_input: ;-------------------------------------------- ; Protection Against Wrapped Sequence Numbers -; First, check timestamp if present +; First, check if timestamp is present ;;;; TODO @@ -681,7 +713,9 @@ align 4 test [edx + TCP_segment.Flags], TH_SYN jz .drop - ; TODO: find sender ip address somewhere! + cmp esi, 0xffffff ; destination ip = 255.255.255.255 ? + jz .drop + ; TODO: check if it's a broadcast or multicast, and drop if so call SOCKET_fork @@ -706,7 +740,6 @@ align 4 mov [eax + TCP_SOCKET.timer_keepalive], TCP_time_keep_interval mov ebx, eax - jmp .trim_then_step6 @@ -725,11 +758,9 @@ align 4 cmp eax, [ebx + TCP_SOCKET.ISS] jle .drop_with_reset - DEBUGF 1,"snd_max = %x\n", [ebx + TCP_SOCKET.SND_MAX] ;;; TODO: set this, but where? - ; mov eax, [edx + TCP_segment.AckNumber] -;; cmp eax, [ebx + TCP_SOCKET.SND_MAX] -;; jg .drop_with_reset + cmp eax, [ebx + TCP_SOCKET.SND_MAX] + jg .drop_with_reset @@: test [edx + TCP_segment.Flags], TH_RST @@ -767,7 +798,7 @@ align 4 push [edx + TCP_segment.SequenceNumber] pop [ebx + TCP_SOCKET.IRS] -;;; TODO: tcp_rcvseqinit + TCP_rcvseqinit ebx mov [ebx + TCP_SOCKET.t_flags], TF_ACKNOW @@ -781,7 +812,7 @@ align 4 DEBUGF 1,"TCP: active open\n" ; TODO: update stats -; TODO: set socket state to connected +; TODO: set general socket state to connected mov [ebx + TCP_SOCKET.t_state], TCB_ESTABLISHED @@ -821,16 +852,16 @@ align 4 .trim_then_step6: - DEBUGF 1,"Trimming window\n" - ;---------------------------- ; trim any data not in window + DEBUGF 1,"Trimming window\n" + mov eax, [ebx + TCP_SOCKET.RCV_NXT] sub eax, [edx + TCP_segment.SequenceNumber] test eax, eax - jz .no_drop + jz .no_duplicate test [edx + TCP_segment.Flags], TH_SYN jz .no_drop @@ -848,10 +879,10 @@ align 4 and [edx + TCP_segment.Flags], not (TH_URG) dec eax - + jz .no_duplicate .no_drop: - DEBUGF 1,"Going to drop %u bytes of data", eax + DEBUGF 1,"Going to drop %u out of %u bytes\n", eax, ecx ; eax holds number of bytes to drop @@ -895,7 +926,7 @@ align 4 .duplicate: - DEBUGF 1,"Duplicate received" + DEBUGF 1,"Duplicate received\n" ;---------------------------------------- ; Update statistics for duplicate packets @@ -924,7 +955,7 @@ align 4 ; Handle data that arrives after process terminates cmp [ebx + SOCKET.PID], 0 - jge @f + jg @f cmp [ebx + TCP_SOCKET.t_state], TCB_CLOSE_WAIT jle @f @@ -936,7 +967,6 @@ align 4 ;;; update stats jmp .drop_with_reset - @@: ;---------------------------------------- @@ -1039,16 +1069,22 @@ align 4 jg .ack_dup jl .ack_nodup + DEBUGF 1,"TCP state = syn received" + ;;;;; .ack_dup: + DEBUGF 1,"Duplicate ACK" + ;;;; .ack_nodup: ;;;; 887 + DEBUGF 1,"New ACK" + ;------------------------------------------------- ; If the congestion window was inflated to account ; for the other side's cached packets, retrace it @@ -1069,7 +1105,6 @@ align 4 mov [ebx + TCP_SOCKET.timer_retransmission], 120 ;;;; TODO: correct this value .all_outstanding: - ;------------------------------------------- ; Open congestion window in response to ACKs @@ -1079,9 +1114,9 @@ align 4 ;------------------------------------------ ; Remove acknowledged data from send buffer - lea eax, [ebx + snd] - mov ecx, ecx ;;;; 943 - 956 - call SOCKET_ring_free + xor ecx, ecx ;;;;;; + lea eax, [ebx + STREAM_SOCKET.snd] + call SOCKET_ring_free ;;;; 943 - 956 ;--------------------------------------- ; Wake up process waiting on send buffer @@ -1196,7 +1231,7 @@ align 4 ;;; 1040-1050 movzx eax, [edx + TCP_segment.UrgentPointer] - add eax, [ebx + rcv.size] + add eax, [ebx + STREAM_SOCKET.rcv + RING_BUFFER.size] cmp eax, SOCKET_MAXDATA jle .not_urgent @@ -1216,17 +1251,35 @@ align 4 .do_data: - DEBUGF 1,"TCP: do data:\n" + DEBUGF 1,"TCP: do data\n" test [edx + TCP_segment.Flags], TH_FIN jnz .process_fin - test [ebx + TCP_SOCKET.t_state], TCB_FIN_WAIT_1 + cmp [ebx + TCP_SOCKET.t_state], TCB_FIN_WAIT_1 jge .dont_do_data + test ecx, ecx + jz .final_processing + DEBUGF 1,"Processing data in segment\n" - ;;; NOW, process the data +;; TODO: check if data is in sequence ! + + movzx eax, [edx + TCP_segment.DataOffset] ;;; todo: remember this in.. edi ? + and eax, 0xf0 + shr al, 2 + + lea esi, [edx + eax] + + or [ebx + TCP_SOCKET.t_flags], TF_DELACK + add [ebx + TCP_SOCKET.RCV_NXT], ecx ;;; right ? + + lea eax, [ebx + STREAM_SOCKET.rcv] + call SOCKET_ring_write + + mov eax, ebx + call SOCKET_notify_owner jmp .final_processing @@ -1248,25 +1301,32 @@ align 4 dd .no_fin ;TCB_CLOSED dd .no_fin ;TCB_LISTEN dd .no_fin ;TCB_SYN_SENT - dd ._1131 ;TCB_SYN_RECEIVED - dd ._1131 ;TCB_ESTABLISHED + dd .fin_syn_est ;TCB_SYN_RECEIVED + dd .fin_syn_est ;TCB_ESTABLISHED dd .no_fin ;TCB_CLOSE_WAIT - dd ._1139 ;TCB_FIN_WAIT_1 + dd .fin_wait1 ;TCB_FIN_WAIT_1 dd .no_fin ;TCB_CLOSING dd .no_fin ;TCB_LAST_ACK - dd ._1147 ;TCB_FIN_WAIT_2 - dd ._1156 ;TCB_TIMED_WAIT + dd .fin_wait2 ;TCB_FIN_WAIT_2 + dd .fin_timed ;TCB_TIMED_WAIT - ._1131: + .fin_syn_est: - ._1139: + jmp .final_processing - ._1147: + .fin_wait1: - ._1156: + jmp .final_processing + .fin_wait2: + + jmp .final_processing + + .fin_timed: + + jmp .final_processing .no_fin: @@ -1277,6 +1337,8 @@ align 4 DEBUGF 1,"Final processing\n" + mov [ebx + SOCKET.lock], 0 + ;;; if debug enabled, output packet ;test ;;;needoutput = 1 @@ -1285,7 +1347,6 @@ align 4 test [ebx + TCP_SOCKET.t_flags], TF_ACKNOW jnz .ack_now - mov [ebx + SOCKET.lock], 0 call kernel_free add esp, 4 ret @@ -1299,7 +1360,6 @@ align 4 call TCP_output pop ebx - mov [ebx + SOCKET.lock], 0 call kernel_free add esp, 4 ret @@ -1322,7 +1382,6 @@ align 4 call TCP_output pop ebx - mov [ebx + SOCKET.lock], 0 call kernel_free add esp, 4 ret @@ -1347,25 +1406,28 @@ align 4 test [edx + TCP_segment.Flags], TH_SYN jnz .respond_syn - mov [ebx + SOCKET.lock], 0 call kernel_free add esp, 4 ret .respond_ack: - ;;;; + mov dl, TH_RST + push ebx call TCP_respond_segment + pop ebx jmp .destroy_new_socket .respond_syn: - ;;;; + mov dl, TH_RST + TH_ACK - call TCP_respond_segment + push ebx + call TCP_respond_socket + pop ebx jmp .destroy_new_socket @@ -1383,7 +1445,6 @@ align 4 ;;;; kill the newly created socket - mov [ebx + SOCKET.lock], 0 call kernel_free add esp, 4 ret @@ -1473,7 +1534,7 @@ TCP_output: test ecx, ecx jnz .no_zero_window - cmp ebx, [eax + snd.size] + cmp ebx, [eax + STREAM_SOCKET.snd + RING_BUFFER.size] jge @f and dl, not (TH_FIN) ; clear the FIN flag ??? how can it be set before? @@ -1491,7 +1552,7 @@ TCP_output: ;;;106 - mov esi, [eax + snd.size] + mov esi, [eax + STREAM_SOCKET.snd + RING_BUFFER.size] cmp esi, ecx jl @f mov esi, ecx @@ -1536,7 +1597,7 @@ TCP_output: mov edi, [eax + TCP_SOCKET.SND_NXT] add edi, esi ; len sub edi, [eax + TCP_SOCKET.SND_UNA] - add edi, [eax + snd.size] + add edi, [eax + STREAM_SOCKET.snd + RING_BUFFER.size] cmp edi, 0 jle @f @@ -1549,7 +1610,7 @@ TCP_output: ; From now on, ecx will be the window we advertise to the other end mov ecx, SOCKET_MAXDATA - sub ecx, [eax + rcv.size] + sub ecx, [eax + STREAM_SOCKET.rcv + RING_BUFFER.size] ;------------------------------ ; Sender silly window avoidance @@ -1706,7 +1767,11 @@ TCP_output: ; edi = header size ; esi = snd ring buff ptr - xor ecx, ecx ;;;;; + mov ecx, [eax + STREAM_SOCKET.snd + RING_BUFFER.size] + cmp ecx, [eax + TCP_SOCKET.t_maxseg] ;;; right? + jle @f + mov ecx, [eax + TCP_SOCKET.t_maxseg] + @@: add ecx, edi ; total TCP segment size ; Start by pushing all TCP header values in reverse order on stack @@ -1733,13 +1798,11 @@ TCP_output: push [eax + TCP_SOCKET.LocalPort] ; .SourcePort dw ? ntohlw [esp] - push edi ; header size + push edi ; header size ; Create the IP packet mov ebx, [eax + IP_SOCKET.LocalIP] ; source ip mov eax, [eax + IP_SOCKET.RemoteIP] ; dest ip -; mov ecx, ; data length -; mov dx, ; fragment id mov di, IP_PROTO_TCP shl 8 + 128 call IPv4_output jz .fail @@ -1747,25 +1810,23 @@ TCP_output: ;----------------------------------------- ; Move TCP header from stack to TCP packet -; pop ecx ; header size -; mov esi, esp -; add esp, ecx -; shr ecx, 2 -; rep movsd - - mov ecx, [esp] - lea esi, [esp+4] + push ecx + mov ecx, [esp+4] + lea esi, [esp+4+4] shr ecx, 2 rep movsd + pop ecx ; full TCP packet size - pop ecx - add esp, ecx + pop esi ; headersize + add esp, esi - mov [esp + 4+4], edx ; packet size mov [esp + 4], eax ; packet ptr + mov [esp + 4+4], edx ; packet size - mov edx, edi - sub edx, ecx + mov edx, edi ; begin of data + sub edx, esi ; begin of packet (edi = begin of data) + push ecx + sub ecx, esi ; data size ;-------------- ; Copy the data @@ -1774,15 +1835,33 @@ TCP_output: ; ecx = buffer size ; edi = ptr to buffer - mov eax, [esp] ; socket ptr - push ecx edx - add eax, snd + mov eax, [esp+4] ; socket ptr + push edx + add eax, STREAM_SOCKET.snd call SOCKET_ring_read pop esi ecx pop eax -;------------------------------------------------------------- -; Create the checksum (we have already pushed IPs onto stack) + test [esi + TCP_segment.Flags], TH_SYN + TH_FIN + jz @f + inc [eax + TCP_SOCKET.SND_NXT] + ;;; TODO: update sentfin flag + @@: + +;; add [eax + TCP_SOCKET.SND_NXT], ecx + + mov edx, [eax + TCP_SOCKET.SND_NXT] + cmp edx, [eax + TCP_SOCKET.SND_MAX] + jle @f + mov [eax + TCP_SOCKET.SND_MAX], edx + + ;;;; TODO: time transmission (420) + @@: + + ;;; TODO: set retransmission timer + +;-------------------- +; Create the checksum DEBUGF 1,"checksum: ptr=%x size=%u\n", esi, ecx @@ -1969,10 +2048,9 @@ TCP_respond_segment: mov ecx, TCP_segment.Data mov di , IP_PROTO_TCP shl 8 + 128 call IPv4_output - test edi, edi jz .error - pop esi cx + push edx eax ;---------------------------------------------------