Subversion Repositories Kolibri OS

Compare Revisions

Regard whitespace Rev 1533 → Rev 1532

/kernel/branches/net/network/socket.inc
169,7 → 169,6
.read_ptr dd ? ; Read pointer
.write_ptr dd ? ; Write pointer
.size dd ? ; Number of bytes buffered
.end:
}
 
virtual at 0
180,9 → 179,10
 
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,6 → 221,14
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
227,6 → 235,7
jl @r
cmp ax, MAX_EPHEMERAL_PORT
jg @r
 
mov [last_UDP_port], ax
 
@@:
235,6 → 244,7
jl @r
cmp ax, MAX_EPHEMERAL_PORT
jg @r
 
mov [last_TCP_port], ax
 
}
308,14 → 318,23
cmp edx, IP_PROTO_TCP
jnz .no_stream
 
mov ebx, eax
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
 
lea eax, [ebx + STREAM_SOCKET.snd]
call SOCKET_ring_create
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.rcv]
call SOCKET_ring_create
 
ret
 
.no_stream:
478,12 → 497,10
mov ebx, [TCP_sequence_num]
add [TCP_sequence_num], 6400
mov [eax + TCP_SOCKET.ISS], ebx
mov [eax + TCP_SOCKET.timer_keepalive], TCP_time_keep_init
mov [eax + TCP_SOCKET.timer_keepalive], 120 ; 120*640ms => 75,6 seconds
 
TCP_sendseqinit eax
;;;; mov [ebx + TCP_SOCKET.timer_retransmission],
 
;;;; mov [ebx + TCP_SOCKET.timer_retransmission], ;; todo: create macro to set retransmission timer
 
push eax
call TCP_output
pop eax
654,9 → 671,6
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,\
693,18 → 707,10
.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
 
 
781,13 → 787,8
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
1027,86 → 1028,58
 
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_write
; SOCKET_ring_add
;
; Adds data to a stream socket, and updates write pointer and size
; Adds data to a stream socket
;
; IN: eax = ptr to ring struct
; ecx = data size
; esi = ptr to data
;
; OUT: ecx = number of bytes stored
; OUT: eax = number of bytes stored
;
;-----------------------------------------------------------------
align 4
SOCKET_ring_write:
SOCKET_ring_add:
 
DEBUGF 1,"SOCKET_ring_write: ringbuff=%x ptr=%x size=%u\n", eax, esi, ecx
DEBUGF 1,"SOCKET_ring_add: ringbuff=%x ptr=%x size=%u\n", eax, esi, ecx
 
add [eax + RING_BUFFER.size], ecx
cmp [eax + RING_BUFFER.size], SOCKET_MAXDATA
mov edi, [eax + RING_BUFFER.size]
add edi, ecx
cmp edi, SOCKET_MAXDATA
jg .too_large
 
mov [eax + RING_BUFFER.size], edi ; update size
.copy:
mov edi, [eax + RING_BUFFER.write_ptr]
DEBUGF 2,"Copying %u bytes from %x to %x\n", ecx, esi, edi
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
 
.copy_more:
push ecx
shr ecx, 1
jnc .nb
movsb
.nb:
shr ecx, 1
jnc .nw
movsw
.nw:
test ecx, ecx
jz .nd
and ecx, 3
rep movsb
pop ecx
shr ecx, 2
rep movsd
.nd:
pop ecx
pop ecx ; >>>> 1/2
DEBUGF 2,"Copied %u bytes\n", 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]
jge .full
jz .full
 
mov [eax + RING_BUFFER.size], SOCKET_MAXDATA ; update size, we will fill buffer completely
 
jmp .copy
 
.full:
1114,57 → 1087,88
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 DOES NOT CLEAR IT FROM MEMORY YET
; reads the data, but let the data remain in the buffer
;
; IN: eax = ptr to ring struct
; ecx = buffer size
; edi = ptr to buffer
;
; OUT: ecx = number of bytes read
; OUT: eax = number of bytes read
;
;-----------------------------------------------------------------
align 4
SOCKET_ring_read:
 
DEBUGF 1,"SOCKET_ring_read: ringbuff=%x ptr=%x size=%u\n", eax, edi, ecx
DEBUGF 1,"SOCKET_ring_read: ringbuff=%x ptr=%x size=%u\n", eax, esi, ecx
 
cmp ecx, [eax + RING_BUFFER.size]
jg .less_data
cmp [eax + RING_BUFFER.size], ecx ; update size
jl .too_large
 
mov esi, [eax + RING_BUFFER.read_ptr] ; update read ptr
.copy:
mov esi, [eax + RING_BUFFER.read_ptr]
push ecx ;<<<< 1
mov edx, [eax + RING_BUFFER.read_ptr]
add edx, ecx
cmp edx, [eax + RING_BUFFER.end_ptr]
jg .copy_in_2
 
DEBUGF 2,"Copying %u bytes from %x to %x\n", ecx, esi, edi
.copy_more:
push ecx
shr ecx, 1
jnc .nb
movsb
.nb:
shr ecx, 1
jnc .nw
movsw
.nw:
test ecx, ecx
jz .nd
and ecx, 3
rep movsb
pop ecx
shr ecx, 2
rep movsd
.nd:
pop ecx
pop ecx ; >>>> 1/2
DEBUGF 2,"Copied %u bytes\n", ecx
 
; .no_data_at_all:
ret
 
.less_data:
.too_large:
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
 
 
;-----------------------------------------------------------------
;
; SOCKET_ring_free
1182,19 → 1186,26
 
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
 
.sumthinwong: ; we could free all available bytes, but that would be stupid, i guess..
add [eax + RING_BUFFER.size], ecx
.moron_input:
xor ecx, ecx
ret
 
1360,8 → 1371,8
cmp [eax + SOCKET.Type], IP_PROTO_TCP
jnz .no_stream
 
stdcall kernel_free, [eax + STREAM_SOCKET.rcv + RING_BUFFER.start_ptr]
stdcall kernel_free, [eax + STREAM_SOCKET.snd + RING_BUFFER.start_ptr]
stdcall kernel_free, [eax + rcv.start_ptr]
stdcall kernel_free, [eax + snd.start_ptr]
.no_stream:
 
push eax ; this will be passed to kernel_free
1389,9 → 1400,9
ret
 
 
; IN: socket nr in ebx
; OUT: socket nr in eax
; preserves edx
; socket nr in ebx
; new socket nr in eax
; preserver edx
 
align 4
SOCKET_fork:
1429,7 → 1440,7
; Get socket structure address by its number
;
; IN: ecx = socket number
; OUT: eax = 0 on error, socket ptr otherwise
; OUT: ecx = 0 on error, socket ptr otherwise
; ZF = set on error
;
;---------------------------------------------------