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 |
; |
;--------------------------------------------------- |