17,30 → 17,9 |
|
$Revision$ |
|
|
TCB_LISTEN equ 1 |
TCB_SYN_SENT equ 2 |
TCB_SYN_RECEIVED equ 3 |
TCB_ESTABLISHED equ 4 |
TCB_FIN_WAIT_1 equ 5 |
TCB_FIN_WAIT_2 equ 6 |
TCB_CLOSE_WAIT equ 7 |
TCB_CLOSING equ 8 |
TCB_LAST_ACK equ 9 |
TCB_TIMED_WAIT equ 10 |
TCB_CLOSED equ 11 |
|
TH_FIN equ 1 shl 0 |
TH_SYN equ 1 shl 1 |
TH_RST equ 1 shl 2 |
TH_PUSH equ 1 shl 3 |
TH_ACK equ 1 shl 4 |
TH_URG equ 1 shl 5 |
|
TWOMSL equ 10 ; # of secs to wait before closing socket |
|
TCP_RETRIES equ 5 ; Number of times to resend a Packet |
TCP_TIMEOUT equ 10 ; resend if not replied to in 1/100 s |
TCP_PACKET_TTL equ 50 ; resend if not replied to in 1/100 s |
TCP_SOCKET_TTL equ 10 ; # of secs to wait before closing socket |
|
TCP_QUEUE_SIZE equ 16 |
|
73,7 → 52,7 |
align 4 |
iglobal |
|
TCBStateHandler: |
stateHandler: |
|
dd stateTCB_LISTEN |
dd stateTCB_SYN_SENT |
90,30 → 69,6 |
endg |
|
|
macro inc_INET reg { |
|
inc byte [reg + 0] |
adc byte [reg + 1], 0 |
adc byte [reg + 2], 0 |
adc byte [reg + 3], 0 |
|
} |
|
|
macro add_INET reg { |
|
rol ecx, 16 |
adc byte [reg + 0], ch |
adc byte [reg + 1], cl |
rol ecx, 16 |
adc byte [reg + 2], ch |
adc byte [reg + 3], cl |
|
} |
|
|
|
|
;----------------------------------------------------------------- |
; |
; TCP_init |
134,8 → 89,13 |
rep stosd |
|
init_queue TCP_IN_QUEUE |
init_queue TCP_OUT_QUEUE |
|
; tcp_out_queue is a special type of queue |
xor eax, eax |
mov esi, TCP_OUT_QUEUE |
mov ecx, TCP_QUEUE_SIZE*tcp_out_queue_entry/4+1 |
rep stosd |
|
ret |
|
|
165,9 → 125,9 |
cmp [ebx + SOCKET_head.Type], IP_PROTO_TCP |
jne .next_socket |
|
; DEBUGF 1, "K : %x-%x: %x-%x-%x-%u\n", [ebx + SOCKET.PID]:2, [ebx + SOCKET.Number]:2, [ebx + SOCKET.LocalPort]:4, [ebx + SOCKET.RemoteIP], [ebx + SOCKET.RemotePort]:4, [ebx + SOCKET.TCBState] |
; DEBUGF 1, "K : %x-%x: %x-%x-%x-%u\n", [ebx + SOCKET.PID]:2, [ebx + SOCKET.Number]:2, [ebx + SOCKET.LocalPort]:4, [ebx + SOCKET.RemoteIP], [ebx + SOCKET.RemotePort]:4, [ebx + SOCKET.state] |
|
cmp [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.TCBTimer], 0 |
cmp [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.timer], 0 |
jne .decrement_tcb |
cmp [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.wndsizeTimer], 0 |
jne .decrement_wnd |
175,10 → 135,10 |
|
.decrement_tcb: |
; decrement it, delete socket if TCB timer = 0 & socket in timewait state |
dec [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.TCBTimer] |
dec [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.timer] |
jnz .next_socket |
|
cmp [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.TCBState], TCB_TIMED_WAIT |
cmp [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.state], TCB_TIMED_WAIT |
jne .next_socket |
|
push [ebx + SOCKET_head.PrevPtr] |
231,30 → 191,33 |
dec [esi + tcp_out_queue_entry.ttl] |
jz .send_it |
.find_next: |
add esi, tcp_out_queue_entry.size |
dec eax |
jz .exit |
jmp .loop |
test ecx, ecx |
jnz .loop |
ret |
|
.send_it: |
push eax ecx esi |
|
mov ebx, [esi + tcp_out_queue_entry.owner] |
push [esi + tcp_out_queue_entry.data_size] |
push [esi + tcp_out_queue_entry.data_ptr] |
mov ebx, [esi + tcp_out_queue_entry.owner] |
|
DEBUGF 1,"Now sending TCP packet %x, size: %u, owner: %x, sendproc %x\n", [esp], [esp+4], ebx, [esi + tcp_out_queue_entry.sendproc] |
call [esi + tcp_out_queue_entry.sendproc] |
|
add esp, 8 |
pop esi ecx eax |
|
dec [esi + tcp_out_queue_entry.retries] |
jz .remove_it |
mov [esi + tcp_out_queue_entry.ttl], TCP_TIMEOUT |
|
mov [esi + tcp_out_queue_entry.ttl], TCP_PACKET_TTL |
jmp .find_next |
|
.remove_it: |
push [esi + tcp_out_queue_entry.data_ptr] |
mov [esi + tcp_out_queue_entry.data_ptr], 0 |
dec [TCP_OUT_QUEUE] |
call kernel_free |
jmp .find_next |
|
278,6 → 241,8 |
align 4 |
TCP_add_to_queue: |
|
DEBUGF 1,"Adding packet to TCP queue, buffer: %x, size: %u, driver: %x, acknum: %x\n", [esp], [esp+4], ebx, edx |
|
cmp [TCP_OUT_QUEUE], TCP_QUEUE_SIZE |
jge .full |
|
291,6 → 256,9 |
loop .loop |
|
.full: ; silently discard the packet |
|
DEBUGF 1,"TCP queue is full!\n" |
|
call kernel_free |
add esp, 4 |
|
304,9 → 272,13 |
mov [eax + tcp_out_queue_entry.retries], TCP_RETRIES |
mov [eax + tcp_out_queue_entry.owner], ebx |
mov [eax + tcp_out_queue_entry.sendproc], esi |
mov [eax + tcp_out_queue_entry.ack_num], edx |
mov [eax + tcp_out_queue_entry.seq_num], edx |
|
inc [TCP_OUT_QUEUE] |
|
sub eax, TCP_OUT_QUEUE+4 |
DEBUGF 1,"Added to queue in pos %u\n", eax |
|
ret |
|
|
332,6 → 304,8 |
|
DEBUGF 1,"TCP_Handler\n" |
|
; TODO: validate checksum |
|
; IP Packet TCP Destination Port = local Port |
; IP Packet SA = Remote IP OR = 0 |
; IP Packet TCP Source Port = remote Port OR = 0 |
358,10 → 332,12 |
cmp [edx + TCP_Packet.SourcePort] , ax |
je .change_state |
test ax, ax |
jne .socket_loop |
jnz .socket_loop |
|
.change_state: |
|
DEBUGF 1,"Found valid socket for packet\n" |
|
push ebx |
lea ebx, [ebx + SOCKET_head.lock] |
call wait_mutex |
373,29 → 349,37 |
; edx is pointer to tcp packet |
|
; as a Packet has been received, update the TCB timer |
mov [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.TCBTimer], TWOMSL |
mov [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.timer], TCP_SOCKET_TTL |
|
; If the received Packet has an ACK bit set, remove any Packets in the resend queue that this received Packet acknowledges |
test [edx + TCP_Packet.Flags], TH_ACK |
jz .call_handler ; No ACK, so no data yet |
|
mov eax, [edx + TCP_Packet.SequenceNumber] ; Calculate sequencenumber in eax |
bswap eax ; |
add eax, ecx ; |
; mov eax, [edx + TCP_Packet.SequenceNumber] ; Calculate sequencenumber in eax |
; bswap eax ; |
; add eax, ecx ; |
|
mov eax, [edx + TCP_Packet.AckNumber] |
;--------- |
|
cmp [TCP_OUT_QUEUE], 0 |
je .call_handler |
push ecx |
|
push ecx |
DEBUGF 1,"Removing all queued packets with smaller ACK\n" |
|
mov ecx, TCP_QUEUE_SIZE |
mov esi, TCP_OUT_QUEUE+4 |
|
.loop: |
cmp [esi + tcp_out_queue_entry.data_ptr], 0 |
jne .maybe_next |
cmp [esi + tcp_out_queue_entry.ack_num], eax |
je .maybe_next |
cmp [esi + tcp_out_queue_entry.seq_num], eax |
jg .maybe_next |
; TODO: check if the packets belong to the same tcp connection ! |
|
DEBUGF 1,"Removing a queued packet\n" |
|
push [esi + tcp_out_queue_entry.data_ptr] |
mov [esi + tcp_out_queue_entry.data_ptr], 0 |
dec [TCP_OUT_QUEUE] |
404,25 → 388,24 |
.maybe_next: |
add esi, tcp_out_queue_entry.size |
loop .loop |
|
pop ecx |
|
.call_handler: |
; Call handler for given TCB state |
mov eax, [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.TCBState] |
mov eax, [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.state] |
DEBUGF 1,"Socket state: %u\n", eax |
|
cmp eax, TCB_LISTEN |
jb .exit |
jb .dump |
cmp eax, TCB_CLOSED |
ja .exit |
ja .dump |
|
dec eax |
shl eax, 2 |
add eax, TCBStateHandler - 4 |
add eax, stateHandler |
|
push .exit |
jmp eax |
call dword[eax] |
|
.exit: |
mov [ebx + SOCKET_head.lock], 0 |
|
.dump: |
DEBUGF 1,"Dumping TCP packet\n" |
call kernel_free |
463,7 → 446,7 |
|
|
push ecx esi eax ; save some variables for later |
add ecx, TCP_Packet.Data |
add ecx, TCP_Packet.Options |
call IPv4_create_packet |
cmp edi, -1 |
je .fail |
485,7 → 468,7 |
mov al, [eax + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.flags] |
mov [edi + TCP_Packet.Flags], al |
|
mov [edi + TCP_Packet.Window], 0x0005 ; 1280 bytes ;;; TODO: read RFC ! |
mov [edi + TCP_Packet.Window], 0x0005 ; 1280 bytes |
mov [edi + TCP_Packet.UrgentPointer], 0 |
mov [edi + TCP_Packet.DataOffset], 0x50 |
mov [edi + TCP_Packet.Checksum], 0 |
493,7 → 476,7 |
; Copy the data |
mov esi, [esp] |
mov ecx, [esp+4] |
add edi, TCP_Packet.Data |
add edi, TCP_Packet.Options |
|
shr ecx, 1 |
jnc .nb |
519,12 → 502,12 |
|
; And now, send it! |
DEBUGF 1,"Sending TCP Packet to device %x\n", ebx |
mov esi, ETH_sender |
lea esi, [ebx+ETH_DEVICE.transmit] |
mov edx, [edi + TCP_Packet.AckNumber] |
jmp TCP_add_to_queue |
|
.fail: |
add esp, 12+4 |
add esp, 12+12+4 |
ret |
|
|
543,14 → 526,15 |
align 4 |
TCP_send_ack: |
|
DEBUGF 1,"Creating TCP ACK\n" |
DEBUGF 1,"Creating TCP ACK, socket: %x, flags: %x\n",eax, bl |
|
mov di , IP_PROTO_TCP |
mov cx , TCP_Packet.Data |
mov ecx, TCP_Packet.Options |
|
push bx eax |
|
; Create an IPv4 Packet of the correct size |
|
mov ebx, [eax + SOCKET_head.end + IPv4_SOCKET.LocalIP] |
mov eax, [eax + SOCKET_head.end + IPv4_SOCKET.RemoteIP] |
|
564,10 → 548,10 |
push [esi + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.SND_NXT] |
pop [edi + TCP_Packet.SequenceNumber] |
|
push dword [esi + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.LocalPort] |
push dword [esi + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.LocalPort] ; both ports at once |
pop dword [edi + TCP_Packet.SourcePort] |
|
push [esi + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.SND_NXT] |
push [esi + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.RCV_NXT] |
pop [edi + TCP_Packet.AckNumber] |
|
pop cx |
575,32 → 559,39 |
mov [edi + TCP_Packet.Window], 0x0005 ; 1280 bytes |
mov [edi + TCP_Packet.UrgentPointer], 0 |
mov [edi + TCP_Packet.DataOffset], 0x50 |
mov [edi + TCP_Packet.Checksum], 0 |
|
push eax edx |
push edx eax |
|
push word TCP_Packet.Data shl 8 |
push IP_PROTO_TCP |
push [esi + SOCKET_head.end + SOCKET_head.end + IPv4_SOCKET.RemoteIP] |
push [esi + SOCKET_head.end + SOCKET_head.end + IPv4_SOCKET.LocalIP] |
lea esi, [esi + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.SND_NXT] |
inc_INET esi |
|
; Now, calculate the checksum for pseudoheader |
; Now, calculate the checksum |
pushw TCP_Packet.Options shl 8 |
pushw IP_PROTO_TCP shl 8 |
pushd [edi-4] ; destination address |
pushd [edi-8] ; source address |
|
xor edx, edx |
mov ecx, TCP_Packet.Options |
mov esi, edi |
call checksum_1 |
mov ecx, 12 |
mov esi, esp |
call checksum_1 |
add esp, 12 ; remove the pseudoheader from stack |
; Now create the final checksum and store it in TCP header |
; and store it in TCP header |
call checksum_2 |
mov [edi + TCP_Packet.Checksum], dx |
|
; And now, send it! |
; And now, send the packet! |
DEBUGF 1,"Sending TCP Packet to device %x\n", ebx |
mov esi, ETH_sender |
mov edx, [edi + TCP_Packet.AckNumber] |
mov esi, [ebx + ETH_DEVICE.transmit] |
mov edx, [edi + TCP_Packet.SequenceNumber] |
jmp TCP_add_to_queue |
|
.fail: |
add esp, 12+4 |
add esp, 2+4 |
ret |
|
|
609,6 → 600,9 |
|
align 4 |
stateTCB_LISTEN: |
|
DEBUGF 1,"TCBStateHandler: Listen\n" |
|
; In this case, we are expecting a SYN Packet |
; For now, if the Packet is a SYN, process it, and send a response |
; If not, ignore it |
631,11 → 625,13 |
mov eax, [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.ISS] |
mov [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.SND_NXT], eax |
|
mov [ebx + SOCKET_head.lock], 0 |
|
; Now construct the response |
mov bl, TH_SYN + TH_ACK |
call TCP_send_ack |
|
mov [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.TCBState], TCB_SYN_RECEIVED |
mov [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.state], TCB_SYN_RECEIVED |
|
; increment SND.NXT in socket |
lea esi, [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.SND_NXT] |
642,11 → 638,15 |
inc_INET esi |
|
.exit: |
mov [ebx + SOCKET_head.lock], 0 |
ret |
|
|
align 4 |
stateTCB_SYN_SENT: |
|
DEBUGF 1,"TCBStateHandler: Syn_Sent\n" |
|
; We are awaiting an ACK to our SYN, with a SYM |
; Look at control flags - expecting an ACK |
|
658,28 → 658,31 |
test al, TH_SYN |
jz .exit |
|
mov [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.TCBState], TCB_SYN_RECEIVED |
push TH_SYN + TH_ACK |
mov [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.state], TCB_SYN_RECEIVED |
pushd TH_SYN + TH_ACK |
jmp .send |
|
.syn_ack: |
mov [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.TCBState], TCB_ESTABLISHED |
push TH_ACK |
mov [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.state], TCB_ESTABLISHED |
pushd TH_ACK |
|
.send: |
; Store the recv.nxt field |
mov eax, [edx + TCP_Packet.SequenceNumber] |
mov [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.IRS], eax |
bswap eax |
inc eax |
bswap eax |
mov [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.RCV_NXT], eax ; Update our recv.nxt field |
mov [ebx + SOCKET_head.lock], 0 |
|
; Update our recv.nxt field |
mov [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.RCV_NXT], eax |
lea esi, [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.RCV_NXT] |
inc_INET esi |
|
; Send an ACK |
mov eax, ebx |
pop ebx |
call TCP_send_ack |
|
.exit: |
mov [ebx + SOCKET_head.lock], 0 |
ret |
|
|
686,6 → 689,9 |
|
align 4 |
stateTCB_SYN_RECEIVED: |
|
DEBUGF 1,"TCBStateHandler: Syn_received\n" |
|
; In this case, we are expecting an ACK Packet |
; For now, if the Packet is an ACK, process it, |
; If not, ignore it |
693,12 → 699,12 |
test [edx + TCP_Packet.Flags], TH_RST |
jz .check_ack |
|
push [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.OrigRemotePort] |
pop [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.RemotePort] |
push [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.OrigRemoteIP] |
pop [ebx + SOCKET_head.end + IPv4_SOCKET.RemoteIP] |
; push [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.OrigRemotePort] |
; pop [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.RemotePort] |
; push [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.OrigRemoteIP] |
; pop [ebx + SOCKET_head.end + IPv4_SOCKET.RemoteIP] |
|
mov [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.TCBState], TCB_LISTEN |
mov [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.state], TCB_LISTEN |
jmp .exit |
|
.check_ack: |
706,9 → 712,10 |
test [edx + TCP_Packet.Flags], TH_ACK |
jz .exit |
|
mov [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.TCBState], TCB_ESTABLISHED |
mov [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.state], TCB_ESTABLISHED |
|
.exit: |
mov [ebx + SOCKET_head.lock], 0 |
ret |
|
|
715,6 → 722,10 |
|
align 4 |
stateTCB_ESTABLISHED: |
|
|
DEBUGF 1,"TCBStateHandler: Established\n" |
|
; Here we are expecting data, or a request to close |
; OR both... |
|
724,6 → 735,7 |
|
; It was a fin or reset. |
|
;;; TODO: write following code: |
; Remove resend entries from the queue - I dont want to send any more data |
; Send an ACK to that fin, and enter closewait state |
|
732,6 → 744,8 |
test [edx + TCP_Packet.Flags], TH_ACK |
jz .exit |
|
DEBUGF 1,"Received ACK\n" |
|
; First, look at the incoming window. If this is less than or equal to 1024, |
; Set the socket window timer to 1. This will stop an additional Packets being queued. |
; ** I may need to tweak this value, since I do not know how many Packets are already queued |
752,7 → 766,7 |
; recv seq is in [sktAddr]+56, in inet format |
; just do a comparision |
mov ecx, [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.RCV_NXT] |
cmp [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.TCBState], TCB_CLOSE_WAIT |
cmp [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.state], TCB_CLOSE_WAIT |
jne @f |
mov ecx, eax |
|
763,11 → 777,12 |
jnz .data |
|
; If we had received a fin, we need to ACK it. |
cmp [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.TCBState], TCB_CLOSE_WAIT |
cmp [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.state], TCB_CLOSE_WAIT |
je .ack |
jmp .exit |
|
.data: |
DEBUGF 1,"Got data!\n" |
mov esi, [esp + 4] |
sub edx, esi |
mov edi, edx |
774,10 → 789,14 |
call socket_internal_receiver |
|
.ack: |
mov [ebx + SOCKET_head.lock], 0 |
; Send an ACK |
mov eax, ebx |
mov bl, TH_ACK |
call TCP_send_ack |
.exit: |
|
mov [ebx + SOCKET_head.lock], 0 |
ret |
|
|
784,6 → 803,9 |
|
align 4 |
stateTCB_FIN_WAIT_1: |
|
DEBUGF 1,"TCBStateHandler: Fin_wait_1\n" |
|
; We can either receive an ACK of a fin, or a fin |
mov al, [edx + TCP_Packet.Flags] |
and al, TH_FIN + TH_ACK |
792,21 → 814,25 |
jne @f |
|
; It was an ACK |
mov [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.TCBState], TCB_FIN_WAIT_2 |
mov [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.state], TCB_FIN_WAIT_2 |
jmp .exit |
|
@@: mov [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.TCBState], TCB_CLOSING |
@@: mov [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.state], TCB_CLOSING |
cmp al, TH_FIN |
je @f |
mov [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.TCBState], TCB_TIMED_WAIT |
mov [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.state], TCB_TIMED_WAIT |
|
@@: lea esi, [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.RCV_NXT] |
inc_INET esi |
|
mov [ebx + SOCKET_head.lock], 0 |
; Send an ACK |
mov eax, ebx |
mov bl, TH_ACK |
call TCP_send_ack |
|
.exit: |
mov [ebx + SOCKET_head.lock], 0 |
ret |
|
|
813,20 → 839,27 |
|
align 4 |
stateTCB_FIN_WAIT_2: |
|
DEBUGF 1,"TCBStateHandler: Fin_wait_2\n" |
|
test [edx + TCP_Packet.Flags], TH_FIN |
jz .exit |
|
; Change state, as we have a fin |
mov [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.TCBState], TCB_TIMED_WAIT |
mov [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.state], TCB_TIMED_WAIT |
|
lea esi, [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.RCV_NXT] |
inc_INET esi |
|
mov [ebx + SOCKET_head.lock], 0 |
|
; Send an ACK |
mov eax, ebx |
mov bl, TH_ACK |
call TCP_send_ack |
|
.exit: |
mov [ebx + SOCKET_head.lock], 0 |
ret |
|
|
833,8 → 866,12 |
|
align 4 |
stateTCB_CLOSE_WAIT: |
|
DEBUGF 1,"TCBStateHandler: close_wait\n" |
; Intentionally left empty |
; socket_close_tcp handles this |
|
mov [ebx + SOCKET_head.lock], 0 |
ret |
|
|
841,22 → 878,32 |
|
align 4 |
stateTCB_CLOSING: |
|
DEBUGF 1,"TCBStateHandler: closingn\n" |
|
; We can either receive an ACK of a fin, or a fin |
test [edx + TCP_Packet.Flags], TH_ACK |
jz .exit |
|
mov [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.TCBState], TCB_TIMED_WAIT |
mov [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.state], TCB_TIMED_WAIT |
|
.exit: |
|
mov [ebx + SOCKET_head.lock], 0 |
ret |
|
|
align 4 |
stateTCB_LAST_ACK: |
|
DEBUGF 1,"TCBStateHandler: last_ackn\n" |
|
; Look at control flags - expecting an ACK |
test [edx + TCP_Packet.Flags], TH_ACK |
jz .exit |
|
mov [ebx + SOCKET_head.lock], 0 |
|
; delete the socket |
stdcall net_socket_free, ebx |
|
866,13 → 913,60 |
|
align 4 |
stateTCB_TIME_WAIT: |
|
DEBUGF 1,"TCBStateHandler: time_wait\n" |
|
mov [ebx + SOCKET_head.lock], 0 |
|
ret |
|
|
align 4 |
stateTCB_CLOSED: |
|
DEBUGF 1,"TCBStateHandler: closed\n" |
|
mov [ebx + SOCKET_head.lock], 0 |
|
ret |
|
|
|
;--------------------------------------------------------------------------- |
; |
; TCP_API |
; |
; This function is called by system function 75 |
; |
; IN: subfunction number in bl |
; device number in bh |
; ecx, edx, .. depends on subfunction |
; |
; OUT: |
; |
;--------------------------------------------------------------------------- |
|
align 4 |
TCP_API: |
|
movzx eax, bh |
shl eax, 2 |
|
test bl, bl |
jz .packets_tx ; 0 |
dec bl |
jz .packets_rx ; 1 |
|
.error: |
mov eax, -1 |
ret |
|
.packets_tx: |
add eax, TCP_PACKETS_TX |
mov eax, [eax] |
ret |
|
.packets_rx: |
add eax, TCP_PACKETS_RX |
mov eax, [eax] |
ret |