Subversion Repositories Kolibri OS

Compare Revisions

Regard whitespace Rev 4422 → Rev 4423

/kernel/branches/Kolibri-acpi/network/IPv4.inc
19,7 → 19,14
$Revision: 3515 $
 
IPv4_MAX_FRAGMENTS = 64
IPv4_MAX_ROUTES = 64
 
IPv4_ROUTE_FLAG_UP = 1 shl 0
IPv4_ROUTE_FLAG_GATEWAY = 1 shl 1
IPv4_ROUTE_FLAG_HOST = 1 shl 2
IPv4_ROUTE_FLAG_D = 1 shl 3 ; Route was created by a redirect
IPv4_ROUTE_FLAG_M = 1 shl 4 ; Route was modified by a redirect
 
struct IPv4_header
 
VersionAndIHL db ? ; Version[0-3 bits] and IHL(header length)[4-7 bits]
54,7 → 61,17
; Ip header begins here (we will need the IP header to re-construct the complete packet)
ends
 
struct IPv4_ROUTE
 
Destination dd ?
Gateway dd ?
Flags dd ?
Use dd ?
Interface dd ?
 
ends
 
 
uglobal
align 4
 
70,6 → 87,8
 
IPv4_FRAGMENT_LIST rb IPv4_MAX_FRAGMENTS * sizeof.IPv4_FRAGMENT_slot
 
IPv4_ROUTES rd IPv4_MAX_ROUTES * sizeof.IPv4_ROUTE
 
endg
 
 
/kernel/branches/Kolibri-acpi/network/icmp.inc
230,7 → 230,7
test eax, eax
jnz @f
call NET_ptr_to_num4
inc [UDP_PACKETS_TX + edi]
inc [ICMP_PACKETS_TX + edi]
@@:
ret
 
/kernel/branches/Kolibri-acpi/network/loopback.inc
35,7 → 35,7
.packets_rx dd 0
 
.link_state dd -1
.hwacc dd 0
.hwacc dd NET_HWACC_TCP_IPv4_IN + NET_HWACC_TCP_IPv4_OUT
 
.namestr db 'loopback', 0
 
/kernel/branches/Kolibri-acpi/network/socket.inc
28,7 → 28,7
PID dd ? ; process ID
TID dd ? ; thread ID
Domain dd ? ; INET/LOCAL/..
Type dd ? ; RAW/STREAM/DGRAP
Type dd ? ; RAW/STREAM/DGRAM
Protocol dd ? ; ICMP/IPv4/ARP/TCP/UDP
errorcode dd ?
device dd ? ; driver pointer, socket pointer if it's an LOCAL socket
92,8 → 92,8
SND_MAX dd ?
 
; congestion control
SND_CWND dd ?
SND_SSTHRESH dd ?
SND_CWND dd ? ; congestion window
SND_SSTHRESH dd ? ; slow start threshold
 
;----------------------
; Transmit timing stuff
141,10 → 141,6
 
seg_next dd ? ; re-assembly queue
 
temp_bits db ?
rb 3 ; align
 
 
ends
 
struct UDP_SOCKET IP_SOCKET
715,13 → 711,14
ret
 
.tcp:
cmp [eax + TCP_SOCKET.t_state], TCPS_SYN_RECEIVED ; state must be LISTEN, SYN_SENT or CLOSED
jb .free
 
call TCP_usrclosed
call TCP_output ;;;; Fixme: is this nescessary??
call SOCKET_free
 
test eax, eax
jz @f
call TCP_output ; If connection is not closed yet, send the FIN
@@:
 
ret
 
 
1562,10 → 1559,10
pop ecx
 
; unlock mutex
push eax ecx
pusha
lea ecx, [eax + RING_BUFFER.mutex]
call mutex_unlock ; TODO: check what registers this function actually destroys
pop ecx eax
popa
 
ret
 
2085,7 → 2082,6
mov eax, [eax + SOCKET.NextPtr]
or eax, eax
jz .error
diff16 "tetten", 0, $
cmp [eax + SOCKET.Number], ecx
jne .next_socket
 
2205,7 → 2201,7
;
; Kernel calls this function when a certain process ends
; This function will check if the process had any open sockets
; And update them accordingly
; And update them accordingly (clean up)
;
; IN: edx = pid
; OUT: /
2251,7 → 2247,7
cmp [eax + SOCKET.Protocol], IP_PROTO_TCP
jne .free
 
call TCP_close
call TCP_disconnect
jmp .closed
 
.free:
2356,22 → 2352,11
and [eax + SOCKET.state], not (SS_ISCONNECTING + SS_ISCONNECTED + SS_ISDISCONNECTING)
or [eax + SOCKET.state], SS_CANTRCVMORE + SS_CANTSENDMORE
 
cmp [eax + SOCKET.Protocol], IP_PROTO_TCP
je .tcp
 
cmp [eax + SOCKET.Protocol], IP_PROTO_UDP
je .udp
 
jmp SOCKET_notify
 
.tcp:
.udp:
mov [eax + UDP_SOCKET.LocalPort], 0 ; UDP and TCP structs store localport at the same offset
mov [eax + UDP_SOCKET.RemotePort], 0
 
jmp SOCKET_notify
 
 
;-----------------------------------------------------------------
;
; SOCKET_cant_recv_more
/kernel/branches/Kolibri-acpi/network/stack.inc
110,7 → 110,7
SS_BLOCKED = 0x8000
 
 
SOCKET_MAXDATA = 4096*32 ; must be 4096*(power of 2) where 'power of 2' is at least 8
SOCKET_MAXDATA = 4096*8 ; must be 4096*(power of 2) where 'power of 2' is at least 8
MAX_backlog = 20 ; maximum backlog for stream sockets
 
; Error Codes
152,7 → 152,8
NET_LINK_IEEE802.11 = 3 ; IEEE 802.11 (WiFi)
 
; Hardware acceleration bits
HWACC_TCP_IPv4 = 1 shl 0
NET_HWACC_TCP_IPv4_IN = 1 shl 0
NET_HWACC_TCP_IPv4_OUT = 1 shl 1
 
struct NET_DEVICE
 
/kernel/branches/Kolibri-acpi/network/tcp.inc
143,7 → 143,63
TCP_input_event dd ?
endg
 
uglobal
align 4
 
TCPS_accepts dd ? ; #SYNs received in LISTEN state
TCPS_closed dd ? ; #connections closed (includes drops)
TCPS_connattempt dd ? ; #connections initiated (calls to connect)
TCPS_conndrops dd ? ; #embryonic connections dropped (before SYN received)
TCPS_connects dd ? ; #connections established actively or passively
TCPS_delack dd ? ; #delayed ACKs sent
TCPS_drops dd ? ; #connections dropped (after SYN received)
TCPS_keepdrops dd ? ; #connections dropped in keepalive (established or awaiting SYN)
TCPS_keepprobe dd ? ; #keepalive probes sent
TCPS_keeptimeo dd ? ; #times keepalive timer or connections-establishment timer expire
TCPS_pawsdrop dd ? ; #segments dropped due to PAWS
TCPS_pcbcachemiss dd ? ; #times PCB cache comparison fails
TCPS_persisttimeo dd ? ; #times persist timer expires
TCPS_predack dd ? ; #times header prediction correct for ACKs
TCPS_preddat dd ? ; #times header prediction correct for data packets
TCPS_rcvackbyte dd ? ; #bytes ACKed by received ACKs
TCPS_rcvackpack dd ? ; #received ACK packets
TCPS_rcvacktoomuch dd ? ; #received ACKs for unsent data
TCPS_rcvafterclose dd ? ; #packets received after connection closed
TCPS_rcvbadoff dd ? ; #packets received with invalid header length
TCPS_rcvbadsum dd ? ; #packets received with checksum errors
TCPS_rcvbyte dd ? ; #bytes received in sequence
TCPS_rcvbyteafterwin dd ? ; #bytes received beyond advertised window
TCPS_rcvdupack dd ? ; #duplicate ACKs received
TCPS_rcvdupbyte dd ? ; #bytes receivedin completely duplicate packets
TCPS_rcvduppack dd ? ; #packets received with completely duplicate bytes
TCPS_rcvoobyte dd ? ; #out-of-order bytes received
TCPS_rcvoopack dd ? ; #out-of-order packets received
TCPS_rcvpack dd ? ; #packets received in sequence
TCPS_rcvpackafterwin dd ? ; #packets with some data beyond advertised window
TCPS_rcvpartdupbyte dd ? ; #duplicate bytes in part-duplicate packets
TCPS_rcvpartduppack dd ? ; #packets with some duplicate data
TCPS_rcvshort dd ? ; #packets received too short
TCPS_rcvtotal dd ? ; #total packets received
TCPS_rcvwinprobe dd ? ; #window probe packets received
TCPS_rcvwinupd dd ? ; #received window update packets
TCPS_rexmttimeo dd ? ; #retransmission timeouts
TCPS_rttupdated dd ? ; #times RTT estimators updated
TCPS_segstimed dd ? ; #segments for which TCP tried to measure RTT
TCPS_sndacks dd ? ; #ACK-only packets sent (data length = 0)
TCPS_sndbyte dd ? ; #data bytes sent
TCPS_sndctrl dd ? ; #control (SYN, FIN, RST) packets sent (data length = 0)
TCPS_sndpack dd ? ; #data packets sent (data length > 0)
TCPS_sndprobe dd ? ; #window probes sent (1 byte of data forced by persist timer)
TCPS_sndrexmitbyte dd ? ; #data bytes retransmitted
TCPS_sndrexmitpack dd ? ; #data packets retransmitted
TCPS_sndtotal dd ? ; total #packets sent
TCPS_sndurg dd ? ; #packets sent with URG-only (data length=0)
TCPS_sndwinup dd ? ; #window update-only packets sent (data length=0)
TCPS_timeoutdrop dd ? ; #connections dropped in retransmission timeout
 
endg
 
 
;-----------------------------------------------------------------
;
; TCP_init
/kernel/branches/Kolibri-acpi/network/tcp_input.inc
78,8 → 78,14
 
 
align 4
TCP_process_input:
proc TCP_process_input
 
locals
dataoffset dd ?
timestamp dd ?
temp_bits db ?
endl
 
xor esi, esi
mov ecx, MANUAL_DESTROY
call create_event
94,6 → 100,7
get_from_queue TCP_queue, TCP_QUEUE_SIZE, sizeof.TCP_queue_entry, .wait
 
push [esi + TCP_queue_entry.timestamp]
pop [timestamp]
push [esi + TCP_queue_entry.buffer_ptr]
 
mov ebx, [esi + TCP_queue_entry.device_ptr]
109,8 → 116,8
je .checksum_ok
 
; re-calculate the checksum (if not already done by hw)
; test [ebx + NET_DEVICE.hwacc], HWACC_TCP_IPv4_IN
; jnz .checksum_ok
test [ebx + NET_DEVICE.hwacc], NET_HWACC_TCP_IPv4_IN
jnz .checksum_ok
 
push ecx esi
pushw [esi + TCP_header.Checksum]
123,12 → 130,13
.checksum_ok:
 
; Verify the data offset
and [edx + TCP_header.DataOffset], 0xf0 ; Calculate TCP segment header size (throwing away unused reserved bits in TCP header)
shr [edx + TCP_header.DataOffset], 2
cmp [edx + TCP_header.DataOffset], sizeof.TCP_header ; Now see if it's at least the size of a standard TCP header
movzx eax, [edx + TCP_header.DataOffset]
and al, 0xf0 ; Calculate TCP segment header size (throwing away unused reserved bits in TCP header)
shr al, 2
cmp al, sizeof.TCP_header ; Now see if it's at least the size of a standard TCP header
jb .drop_no_socket ; If not, drop the packet
mov [dataoffset], eax
 
movzx eax, [edx + TCP_header.DataOffset]
sub ecx, eax ; substract TCP header size from total segment size
jb .drop_no_socket ; If total segment size is less then the advertised header size, drop packet
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: %u bytes of data\n", ecx
211,7 → 219,7
;---------------------------
; disable all temporary bits
 
mov [ebx + TCP_SOCKET.temp_bits], 0
mov [temp_bits], 0
 
;---------------------------------------
; unscale the window into a 32 bit value
245,7 → 253,7
 
mov ebx, eax
 
mov [ebx + TCP_SOCKET.temp_bits], TCP_BIT_DROPSOCKET ;;; FIXME: should we take over bits from previous socket?
mov [temp_bits], TCP_BIT_DROPSOCKET
 
push dword [edi + 4] ; Ipv4 destination addres
pop [ebx + IP_SOCKET.LocalIP]
267,18 → 275,18
;--------------------
; Process TCP options
 
;;; FIXME: for LISTEN, options should be called after we determined route, we need it for MSS
;;; cmp [ebx + TCP_SOCKET.t_state], TCPS_LISTEN ; no options when in listen state
;;; jz .not_uni_xfer ; also no header prediction
 
push ecx
 
movzx ecx, [edx + TCP_header.DataOffset]
mov ecx, [dataoffset]
cmp ecx, sizeof.TCP_header ; Does header contain any options?
je .no_options
 
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: Segment has options\n"
 
;;; FIXME: for LISTEN, options should be called after we determined route, we need it for MSS
;;; cmp [ebx + TCP_SOCKET.t_state], TCPS_LISTEN ; no options when in listen state
;;; jz .not_uni_xfer ; also no header prediction
 
add ecx, edx
lea esi, [edx + sizeof.TCP_header]
 
311,9 → 319,10
test [edx + TCP_header.Flags], TH_SYN
jz @f
 
xor eax, eax
lodsw
rol ax, 8
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: Maxseg=%u\n", ax
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: Maxseg=%u\n", eax
call TCP_mss
@@:
jmp .opt_loop
366,10 → 375,11
@@:
 
lodsd
bswap eax
mov [ebx + TCP_SOCKET.ts_val], eax
lodsd ; timestamp echo reply
mov [ebx + TCP_SOCKET.ts_ecr], eax
or [ebx + TCP_SOCKET.temp_bits], TCP_BIT_TIMESTAMP
or [temp_bits], TCP_BIT_TIMESTAMP
 
; Since we have a timestamp, lets do the paws test right away!
 
380,11 → 390,11
test eax, eax
jz .no_paws
cmp eax, [ebx + TCP_SOCKET.ts_val]
jge .no_paws
jbe .no_paws
 
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: PAWS: detected an old segment\n"
 
mov eax, [esp+4+4] ; tcp_now
mov eax, [timestamp]
sub eax, [ebx + TCP_SOCKET.ts_recent_age]
 
pop ecx
474,9 → 484,9
 
; Update RTT estimators
 
test [ebx + TCP_SOCKET.temp_bits], TCP_BIT_TIMESTAMP
test [temp_bits], TCP_BIT_TIMESTAMP
jz .no_timestamp_rtt
mov eax, [esp + 4] ; timestamp when this segment was received
mov eax, [timestamp]
sub eax, [ebx + TCP_SOCKET.ts_ecr]
inc eax
call TCP_xmit_timer
536,12 → 546,11
 
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: Header prediction: we are receiving %u bytes\n", ecx
 
add [ebx + TCP_SOCKET.RCV_NXT], ecx ; Update sequence number with number of bytes we have copied
 
movzx esi, [edx + TCP_header.DataOffset]
mov esi, [dataoffset]
add esi, edx
lea eax, [ebx + STREAM_SOCKET.rcv]
call SOCKET_ring_write ; Add the data to the socket buffer
add [ebx + TCP_SOCKET.RCV_NXT], ecx ; Update sequence number with number of bytes we have copied
 
mov eax, ebx
call SOCKET_notify
558,12 → 567,13
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: Header prediction failed\n"
 
; Calculate receive window size
 
push edx
mov eax, SOCKETBUFFSIZE
mov eax, SOCKET_MAXDATA
sub eax, [ebx + STREAM_SOCKET.rcv.size]
DEBUGF DEBUG_NETWORK_VERBOSE, "Space in receive buffer=%d\n", eax
mov edx, [ebx + TCP_SOCKET.RCV_ADV]
sub edx, [ebx + TCP_SOCKET.RCV_NXT]
DEBUGF DEBUG_NETWORK_VERBOSE, "Current advertised window=%d\n", edx
cmp eax, edx
jg @f
mov eax, edx
583,8 → 593,9
;----------------------------
; trim any data not in window
 
; check for duplicate data at beginning of segment (635)
; 1. Check for duplicate data at beginning of segment
 
; Calculate number of bytes we need to drop
mov eax, [ebx + TCP_SOCKET.RCV_NXT]
sub eax, [edx + TCP_header.SequenceNumber]
jle .no_duplicate
609,7 → 620,7
dec eax
.no_dup_syn:
 
; Check for entire duplicate segment (646)
; 2. Check for entire duplicate segment
cmp eax, ecx ; eax holds number of bytes to drop, ecx is data size
jb .duplicate
jnz @f
623,16 → 634,19
 
; send an ACK and resynchronize and drop any data.
; But keep on processing for RST or ACK
DEBUGF DEBUG_NETWORK_VERBOSE, "616\n"
or [ebx + TCP_SOCKET.t_flags], TF_ACKNOW
mov eax, ecx
;TODO: update stats
 
;;; TODO: update stats
 
;-----------------------------------------------
; Remove duplicate data and update urgent offset
 
.duplicate:
;;; TODO: 677
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: trimming duplicate data\n"
 
; Trim data from left side of window
add [dataoffset], eax
add [edx + TCP_header.SequenceNumber], eax
sub ecx, eax
 
643,10 → 657,10
@@:
 
;--------------------------------------------------
; Handle data that arrives after process terminates (687)
; Handle data that arrives after process terminates
 
.no_duplicate:
cmp [ebx + SOCKET.PID], 0
cmp [ebx + SOCKET.PID], 0 ;;; TODO: use socket flags instead??
jne .not_terminated
cmp [ebx + TCP_SOCKET.t_state], TCPS_CLOSE_WAIT
jbe .not_terminated
659,7 → 673,7
jmp .respond_seg_reset
 
;----------------------------------------
; Remove data beyond right edge of window (700-736)
; Remove data beyond right edge of window
 
.not_terminated:
mov eax, [edx + TCP_header.SequenceNumber]
688,32 → 702,29
jmp .findpcb ; FIXME: skip code for unscaling window, ...
.no_new_request:
 
; If window is closed can only take segments at window edge, and have to drop data and PUSH from
; If window is closed, we can only take segments at window edge, and have to drop data and PUSH from
; incoming segments. Continue processing, but remember to ACK. Otherwise drop segment and ACK
 
cmp [ebx + TCP_SOCKET.RCV_WND], 0
jne .drop_after_ack
mov eax, [edx + TCP_header.SequenceNumber]
cmp eax, [ebx + TCP_SOCKET.RCV_NXT]
mov esi, [edx + TCP_header.SequenceNumber]
cmp esi, [ebx + TCP_SOCKET.RCV_NXT]
jne .drop_after_ack
 
DEBUGF DEBUG_NETWORK_VERBOSE, "690\n"
or [ebx + TCP_SOCKET.t_flags], TF_ACKNOW
;;; TODO: update stats
jmp .no_excess_data
.dont_drop_all:
;;; TODO: update stats
;;; TODO: 733
 
sub ecx, eax
and [ebx + TCP_SOCKET.t_flags], not (TH_PUSH or TH_FIN)
DEBUGF DEBUG_NETWORK_VERBOSE, "Trimming %u bytes from the right of the window\n"
sub ecx, eax ; remove data from the right side of window (decrease data length)
and [edx + TCP_header.Flags], not (TH_PUSH or TH_FIN)
.no_excess_data:
 
;-----------------
; Record timestamp (737-746)
; Record timestamp
 
; If last ACK falls within this segments sequence numbers, record its timestamp
test [ebx + TCP_SOCKET.temp_bits], TCP_BIT_TIMESTAMP
test [temp_bits], TCP_BIT_TIMESTAMP
jz .no_timestamp
mov eax, [ebx + TCP_SOCKET.last_ack_sent]
sub eax, [edx + TCP_header.SequenceNumber]
727,7 → 738,7
 
DEBUGF DEBUG_NETWORK_VERBOSE, "Recording timestamp\n"
 
mov eax, [esp + 4] ; tcp_now
mov eax, [timestamp]
mov [ebx + TCP_SOCKET.ts_recent_age], eax
mov eax, [ebx + TCP_SOCKET.ts_val]
mov [ebx + TCP_SOCKET.ts_recent], eax
882,7 → 893,9
 
mov eax, [ebx + TCP_SOCKET.SND_WND]
cmp eax, [ebx + TCP_SOCKET.SND_CWND]
cmova eax, [ebx + TCP_SOCKET.SND_CWND]
jbe @f
mov eax, [ebx + TCP_SOCKET.SND_CWND]
@@:
shr eax, 1
push edx
xor edx, edx
993,13 → 1006,13
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: acceptable ACK for %u bytes\n", edi
 
;------------------------------------------
; RTT measurements and retransmission timer (912-926)
; RTT measurements and retransmission timer
 
; If we have a timestamp, update smoothed RTT
 
test [ebx + TCP_SOCKET.temp_bits], TCP_BIT_TIMESTAMP
test [temp_bits], TCP_BIT_TIMESTAMP
jz .timestamp_not_present
mov eax, [esp+4]
mov eax, [timestamp]
sub eax, [ebx + TCP_SOCKET.ts_ecr]
inc eax
call TCP_xmit_timer
1028,7 → 1041,7
cmp eax, [edx + TCP_header.AckNumber]
jne .more_data
and [ebx + TCP_SOCKET.timer_flags], not timer_flag_retransmission
or [ebx + TCP_SOCKET.temp_bits], TCP_BIT_NEEDOUTPUT
or [temp_bits], TCP_BIT_NEEDOUTPUT
jmp .no_restart
.more_data:
test [ebx + TCP_SOCKET.timer_flags], timer_flag_persist
1067,7 → 1080,9
pop ecx
 
cmp esi, eax
cmova esi, eax
jbe @f
mov esi, eax
@@:
mov [ebx + TCP_SOCKET.SND_CWND], esi
 
;------------------------------------------
1175,13 → 1190,10
call mutex_unlock
pop ebx
 
push ebx
mov eax, ebx
call TCP_disconnect
pop ebx
call TCP_close
jmp .drop_no_socket
 
jmp .destroy_new_socket
 
.ack_tw:
mov [ebx + TCP_SOCKET.timer_timed_wait], 2 * TCP_time_MSL
or [ebx + TCP_SOCKET.timer_flags], timer_flag_wait
1228,7 → 1240,7
TCP_rcvseqinit ebx
 
mov [ebx + TCP_SOCKET.t_state], TCPS_SYN_RECEIVED
mov [ebx + TCP_SOCKET.t_flags], TF_ACKNOW
or [ebx + TCP_SOCKET.t_flags], TF_ACKNOW
mov [ebx + TCP_SOCKET.timer_keepalive], TCP_time_keep_interval ;;;; macro
or [ebx + TCP_SOCKET.timer_flags], timer_flag_keepalive
 
1238,7 → 1250,7
lea eax, [ebx + STREAM_SOCKET.rcv]
call SOCKET_ring_create
 
and [ebx + TCP_SOCKET.temp_bits], not TCP_BIT_DROPSOCKET
and [temp_bits], not TCP_BIT_DROPSOCKET
 
pusha
mov eax, ebx
1355,8 → 1367,17
 
inc [edx + TCP_header.SequenceNumber]
 
;;; TODO: Drop any received data that follows receive window (590)
; Drop any received data that doesnt fit in the receive window.
cmp ecx, [ebx + TCP_SOCKET.RCV_WND]
jbe .dont_trim
 
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: received data does not fit in window, trimming %u bytes\n", eax
mov ecx, [ebx + TCP_SOCKET.RCV_WND]
and [edx + TCP_header.Flags], not (TH_FIN)
;;; TODO: update stats
 
.dont_trim:
 
mov eax, [edx + TCP_header.SequenceNumber]
mov [ebx + TCP_SOCKET.RCV_UP], eax
dec eax
1409,7 → 1430,7
push [edx + TCP_header.AckNumber]
pop [ebx + TCP_SOCKET.SND_WL2]
 
or [ebx + TCP_SOCKET.temp_bits], TCP_BIT_NEEDOUTPUT
or [temp_bits], TCP_BIT_NEEDOUTPUT
 
.no_window_update:
 
1475,7 → 1496,7
or [ebx + TCP_SOCKET.t_flags], TF_DELACK
 
pusha
movzx esi, [edx + TCP_header.DataOffset]
mov esi, [dataoffset]
add esi, edx
lea eax, [ebx + STREAM_SOCKET.rcv]
call SOCKET_ring_write ; Add the data to the socket buffer
1489,16 → 1510,16
jmp .data_done
 
.out_of_order:
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP data is out of order!\nSequencenumber is %u, we expected %u.\n", \
[edx + TCP_header.SequenceNumber], [ebx + TCP_SOCKET.RCV_NXT]
 
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP data is out of order\n"
 
; Uh-oh, some data is out of order, lets call TCP reassemble for help
 
call TCP_reassemble
 
DEBUGF DEBUG_NETWORK_VERBOSE, "1470\n"
; Generate ACK immediately, to let the other end know that a segment was received out of order,
; and to tell it what sequence number is expected. This aids the fast-retransmit algorithm.
or [ebx + TCP_SOCKET.t_flags], TF_ACKNOW
 
.data_done:
 
;---------------
1517,7 → 1538,7
mov eax, ebx
call SOCKET_cant_recv_more
 
mov [ebx + TCP_SOCKET.t_flags], TF_ACKNOW
or [ebx + TCP_SOCKET.t_flags], TF_ACKNOW
inc [ebx + TCP_SOCKET.RCV_NXT]
 
.not_first_fin:
1539,31 → 1560,56
dd .fin_timed ; TCPS_TIMED_WAIT
 
.fin_syn_est:
 
mov [ebx + TCP_SOCKET.t_state], TCPS_CLOSE_WAIT
jmp .final_processing
 
.fin_wait1:
 
mov [ebx + TCP_SOCKET.t_state], TCPS_CLOSING
jmp .final_processing
 
.fin_wait2:
 
mov [ebx + TCP_SOCKET.t_state], TCPS_TIMED_WAIT
mov eax, ebx
call TCP_cancel_timers
mov [ebx + TCP_SOCKET.timer_timed_wait], 2 * TCP_time_MSL
or [ebx + TCP_SOCKET.timer_flags], timer_flag_wait
call SOCKET_is_disconnected
jmp .final_processing
 
.fin_timed:
mov [ebx + TCP_SOCKET.timer_timed_wait], 2 * TCP_time_MSL
or [ebx + TCP_SOCKET.timer_flags], timer_flag_wait
jmp .final_processing
 
;-----------------
; Final processing
 
.final_processing:
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: Final processing\n"
 
push ebx
lea ecx, [ebx + SOCKET.mutex]
call mutex_unlock
pop eax
 
test [temp_bits], TCP_BIT_NEEDOUTPUT
jnz .need_output
 
test [eax + TCP_SOCKET.t_flags], TF_ACKNOW
jz .dumpit
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: ACK now!\n"
 
.need_output:
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: need output\n"
call TCP_output
 
.dumpit:
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: dumping\n"
 
call NET_packet_free
jmp .loop
 
 
;-----------------
; Drop the segment
 
 
.drop_after_ack:
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: Drop after ACK\n"
 
1598,35 → 1644,6
jnz .respond_syn
jmp .dumpit
 
;-----------------
; Final processing
 
.final_processing:
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: Final processing\n"
 
push ebx
lea ecx, [ebx + SOCKET.mutex]
call mutex_unlock
pop eax
 
test [eax + TCP_SOCKET.temp_bits], TCP_BIT_NEEDOUTPUT
jnz .need_output
 
test [eax + TCP_SOCKET.t_flags], TF_ACKNOW
jz .dumpit
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: ACK now!\n"
 
.need_output:
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: need output\n"
call TCP_output
 
.dumpit:
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: dumping\n"
 
call NET_packet_free
add esp, 4
jmp .loop
 
;---------
; Respond
 
1687,7 → 1704,7
popa
 
.destroy_new_socket:
test [ebx + TCP_SOCKET.temp_bits], TCP_BIT_DROPSOCKET
test [temp_bits], TCP_BIT_DROPSOCKET
jz .drop_no_socket
 
mov eax, ebx
1697,5 → 1714,6
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: Drop (no socket)\n"
 
call NET_packet_free
add esp, 4
jmp .loop
 
endp
/kernel/branches/Kolibri-acpi/network/tcp_output.inc
21,15 → 21,18
; TCP_output
;
; IN: eax = socket pointer
; OUT: eax = 0 on success/errorcode
;
; OUT: /
;
;-----------------------------------------------------------------
align 4
TCP_output:
proc TCP_output
 
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_output: socket=%x\n", eax
locals
temp_bits db ?
endl
 
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_output: socket=%x state=%u\n", eax, [eax + TCP_SOCKET.t_state]
 
push eax
lea ecx, [eax + SOCKET.mutex]
call mutex_lock
57,7 → 60,7
 
.not_idle:
.again:
mov [eax + TCP_SOCKET.temp_bits], 0
mov [temp_bits], 0
 
mov ebx, [eax + TCP_SOCKET.SND_NXT] ; calculate offset (71)
sub ebx, [eax + TCP_SOCKET.SND_UNA] ;
145,7 → 148,7
jbe @f
 
mov esi, [eax + TCP_SOCKET.t_maxseg]
or [eax + TCP_SOCKET.temp_bits], TCP_BIT_SENDALOT
or [temp_bits], TCP_BIT_SENDALOT
@@:
 
;--------------------------------------------
173,7 → 176,7
jz .len_zero
 
cmp esi, [eax + TCP_SOCKET.t_maxseg]
je TCP_send
je .send
 
add ebx, esi ; offset + length
cmp ebx, [eax + STREAM_SOCKET.snd.size]
180,24 → 183,24
jb @f
 
test [eax + TCP_SOCKET.t_flags], TF_NODELAY
jnz TCP_send
jnz .send
 
mov ebx, [eax + TCP_SOCKET.SND_MAX]
cmp ebx, [eax + TCP_SOCKET.SND_UNA]
je TCP_send
je .send
@@:
 
test [eax + TCP_SOCKET.t_force], -1 ;;;
jnz TCP_send
jnz .send
 
mov ebx, [eax + TCP_SOCKET.max_sndwnd]
shr ebx, 1
cmp esi, ebx
jae TCP_send
jae .send
 
mov ebx, [eax + TCP_SOCKET.SND_NXT]
cmp ebx, [eax + TCP_SOCKET.SND_MAX]
jb TCP_send
jb .send
 
.len_zero:
 
229,9 → 232,10
mov edi, [eax + TCP_SOCKET.t_maxseg]
shl edi, 1
 
; cmp ebx, edi
; jae TCP_send
cmp ebx, edi
jae .send
 
shl ebx, 1
; cmp ebx, [eax + TCP_SOCKET.] ;;; TODO: check with receive buffer high water mark
; jae TCP_send
 
240,17 → 244,15
;--------------------------
; Should a segment be sent? (174)
 
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_output: 174\n"
 
test [eax + TCP_SOCKET.t_flags], TF_ACKNOW ; we need to ACK
jnz TCP_send
jnz .send
 
test dl, TH_SYN + TH_RST ; we need to send a SYN or RST
jnz TCP_send
jnz .send
 
mov ebx, [eax + TCP_SOCKET.SND_UP] ; when urgent pointer is beyond start of send bufer
cmp ebx, [eax + TCP_SOCKET.SND_UNA]
ja TCP_send
ja .send
 
test dl, TH_FIN
jz .enter_persist ; no reason to send, enter persist state
258,11 → 260,11
; FIN was set, only send if not already sent, or on retransmit
 
test [eax + TCP_SOCKET.t_flags], TF_SENTFIN
jz TCP_send
jz .send
 
mov ebx, [eax + TCP_SOCKET.SND_NXT]
cmp ebx, [eax + TCP_SOCKET.SND_UNA]
je TCP_send
je .send
 
;--------------------
; Enter persist state (191)
298,13 → 300,6
ret
 
 
 
 
 
 
 
 
 
;-----------------------------------------------
;
; Send a segment (222)
314,8 → 309,7
; dl = flags
;
;-----------------------------------------------
align 4
TCP_send:
.send:
 
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_send: socket=%x length=%u flags=%x\n", eax, esi, dl
 
406,9 → 400,41
jbe .no_overflow
 
mov esi, [eax + TCP_SOCKET.t_maxseg]
or [eax + TCP_SOCKET.temp_bits], TCP_BIT_SENDALOT
or [temp_bits], TCP_BIT_SENDALOT
.no_overflow:
 
;----------------------------------------------------
; Calculate the receive window.
; Dont shrink window, but avoid silly window syndrome
 
mov ebx, SOCKET_MAXDATA
sub ebx, [eax + STREAM_SOCKET.rcv.size]
 
cmp ebx, SOCKET_MAXDATA/4
jae @f
cmp ebx, [eax + TCP_SOCKET.t_maxseg]
jae @f
xor ebx, ebx
@@:
 
cmp ebx, TCP_max_win
jbe @f
mov ebx, TCP_max_win
@@:
 
mov ecx, [eax + TCP_SOCKET.RCV_ADV]
sub ecx, [eax + TCP_SOCKET.RCV_NXT]
cmp ebx, ecx
ja @f
mov ebx, ecx
@@:
 
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_send: window = %u\n", ebx
 
mov cl, [eax + TCP_SOCKET.RCV_SCALE]
shr ebx, cl
xchg bl, bh
 
;-----------------------------------------------------------------
; Start by pushing all TCP header values in reverse order on stack
; (essentially, creating the tcp header on the stack!)
415,7 → 441,7
 
pushw 0 ; .UrgentPointer dw ?
pushw 0 ; .Checksum dw ?
pushw 0x00a0 ; .Window dw ? ;;;;;;; FIXME (370)
pushw bx ; .Window dw ?
shl edi, 2 ; .DataOffset db ? only 4 left-most bits
shl dx, 8
or dx, di ; .Flags db ?
534,7 → 560,13
;--------------------
; Create the checksum
 
xor dx, dx
test [ebx + NET_DEVICE.hwacc], NET_HWACC_TCP_IPv4_OUT
jnz .checksum_ok
 
TCP_checksum (eax + IP_SOCKET.LocalIP), (eax + IP_SOCKET.RemoteIP)
 
.checksum_ok:
mov [esi + TCP_header.Checksum], dx
 
;----------------
566,7 → 598,7
push [eax + TCP_SOCKET.RCV_NXT]
pop [eax + TCP_SOCKET.last_ack_sent]
 
; and flags
; clear the ACK flags
and [eax + TCP_SOCKET.t_flags], not (TF_ACKNOW + TF_DELACK)
 
;--------------
582,7 → 614,7
;-----------------------------
; Check if we need more output
 
test [eax + TCP_SOCKET.temp_bits], TCP_BIT_SENDALOT
test [temp_bits], TCP_BIT_SENDALOT
jnz TCP_output.again
 
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_send: success!\n"
622,7 → 654,4
ret
 
 
 
 
 
 
endp
/kernel/branches/Kolibri-acpi/network/tcp_subr.inc
152,7 → 152,9
 
mov [eax + TCP_SOCKET.t_state], TCPS_CLOSED
 
push eax
call TCP_output
pop eax
 
;;; TODO: update stats
 
169,16 → 171,43
 
 
 
;-------------------------
;
; TCP_disconnect
;
; IN: eax = socket ptr
; OUT: eax = socket ptr / 0
;
;-------------------------
align 4
TCP_disconnect:
 
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_disconnect: %x\n", eax
 
cmp [eax + TCP_SOCKET.t_state], TCPS_ESTABLISHED
jb TCP_close ; Connection not yet synchronised, just get rid of the socket
 
; TODO: implement LINGER
 
call SOCKET_is_disconnecting
call TCP_usrclosed
 
test eax, eax
jz @f
push eax
call TCP_output
pop eax
@@:
 
ret
 
 
;-------------------------
;
; TCP_close
;
; IN: eax = socket ptr
; OUT: eax = socket ptr
; OUT: /
;
;-------------------------
align 4
190,8 → 219,10
;;; TODO: update slow start threshold
 
call SOCKET_is_disconnected
;; call SOCKET_free
call SOCKET_free
 
xor eax, eax
 
ret
 
 
/kernel/branches/Kolibri-acpi/network/tcp_usreq.inc
1,6 → 1,6
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2012. All rights reserved. ;;
;; Copyright (C) KolibriOS team 2004-2013. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;; Part of the TCP/IP network stack for KolibriOS ;;
57,7 → 57,6
 
.wait1:
mov [eax + TCP_SOCKET.t_state], TCPS_FIN_WAIT_1
; TODO: set timer?
pop ebx
ret
 
68,7 → 67,6
 
.disc:
call SOCKET_is_disconnected
; TODO: set timer?
.ret:
pop ebx
ret
202,35 → 200,4
stdcall cancel_timer_hs, [eax + TCP_SOCKET.timer_connect]
 
xor eax, eax
ret
 
 
 
 
;-------------------------
;
; TCP_disconnect
;
; IN: eax = socket ptr
; OUT: eax = socket ptr
;
;-------------------------
align 4
TCP_disconnect:
 
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_disconnect: %x\n", eax
 
cmp [eax + TCP_SOCKET.t_state], TCPS_ESTABLISHED
jb TCP_close
 
 
; TODO: implement LINGER ?
 
call SOCKET_is_disconnecting
call TCP_usrclosed
 
push eax
call TCP_output
pop eax
 
ret