Subversion Repositories Kolibri OS

Compare Revisions

Regard whitespace Rev 913 → Rev 914

/kernel/branches/kolibri_pe/network/socket.inc
77,21 → 77,23
; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
; 72| Retransmit queue # NOW WINDOW SIZE TIMER INTEL format|
; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
; 76| RX offset from
; 76| RX Data |
; 76| RX Data Buffer |
; +-+-+-.......... -+
 
 
; so, define struct
struc SOCKET
{ .Status dd ? ;+00 - Status ( of this buffer )
{
.PrevPtr dd ?
.NextPtr dd ?
.Status dd ? ;+00 - Status ( of this buffer )
.PID dd ? ;+04 - Application Process ID
.LocalIP dd ? ;+08 - Local IP Address
.LocalPort dw ? ;+12 - Local Port
.UnusedL dw ? ;+14 - may be removed in future
.RemoteIP dd ? ;+16 - Remote IP Address
.RemotePort dw ? ;+20 - Remote Port
.UnusedR dw ? ;+22 - may be removed in future
.OrigRemoteIP dd ?
.OrigRemotePort dw ?
.rxDataCount dd ? ;+24 - Rx Data Count
.TCBState dd ? ;+28 - TCB STATE
.TCBTimer dd ? ;+32 - TCB Timer (seconds)
113,21 → 115,132
end virtual
 
; simple macro calcing real memory address of SOCKET struct by socket's
macro Index2RealAddr reg
{
shl reg, 12
add reg, sockets
}
;macro Index2RealAddr reg
;{
; shl reg, 12
; add reg, sockets
;}
 
;Constants
; current socket statuses
SOCK_EMPTY equ 0 ; socket not in use
SOCK_OPEN equ 1 ; open issued, but no data sent
SOCK_EMPTY = 0 ; socket not in use
SOCK_OPEN = 1 ; open issued, but no data sent
 
; TCP opening modes
SOCKET_PASSIVE equ 0
SOCKET_ACTIVE equ 1
 
proc net_socket_alloc stdcall uses ebx ecx edx edi
mov ecx, SOCKETBUFFSIZE
mov edx, PG_SW
call @mem_alloc@8
DEBUGF 1, "K : net_socket_alloc (0x%x)\n", eax
or eax, eax
jz .exit
 
push eax
mov edi, eax
mov ecx, SOCKETBUFFSIZE / 4
cld
xor eax, eax
rep stosd
pop eax
 
mov ebx, net_sockets
push [ebx + SOCKET.NextPtr]
mov [ebx + SOCKET.NextPtr], eax
mov [eax + SOCKET.PrevPtr], ebx
pop ebx
mov [eax + SOCKET.NextPtr], ebx
or ebx, ebx
jz @f
mov [ebx + SOCKET.PrevPtr], eax
 
@@: mov ebx, [TASK_BASE]
mov ebx, [ebx + TASKDATA.pid]
mov [eax + SOCKET.PID], ebx
 
.exit:
ret
endp
 
proc net_socket_free stdcall uses ebx ecx edx, sock:DWORD
mov eax, [sock]
DEBUGF 1, "K : net_socket_free (0x%x)\n", eax
or eax, eax
jz .error
 
mov ebx, net_sockets
mov ecx, [TASK_BASE]
mov ecx, [ecx + TASKDATA.pid]
.next_socket:
mov ebx, [ebx + SOCKET.NextPtr]
or ebx, ebx
jz .error
cmp ebx, eax
jne .next_socket
;cmp [ebx + SOCKET.PID], ecx
;jne .next_socket
 
mov ebx, [eax + SOCKET.NextPtr]
mov eax, [eax + SOCKET.PrevPtr]
mov [eax + SOCKET.NextPtr], ebx
or ebx, ebx
jz @f
mov [ebx + SOCKET.PrevPtr], eax
 
@@:
mov ecx, [sock]
call @mem_free@4
ret
 
.error:
DEBUGF 1, "K : failed\n"
ret
endp
 
proc net_socket_num_to_addr stdcall uses ebx ecx, x:DWORD
; FIXME: do real transform
mov eax, [x]
mov ebx, net_sockets
mov ecx, [TASK_BASE]
mov ecx, [ecx + TASKDATA.pid]
.next_socket:
mov ebx, [ebx + SOCKET.NextPtr]
or ebx, ebx
jz .error
cmp ebx, eax
jne .next_socket
;cmp [ebx + SOCKET.PID], ecx
;jne .next_socket
ret
 
.error:
xor eax, eax
ret
endp
 
proc net_socket_addr_to_num stdcall uses ebx ecx, x:DWORD
; FIXME: do real transform
mov eax, [x]
mov ebx, net_sockets
mov ecx, [TASK_BASE]
mov ecx, [ecx + TASKDATA.pid]
.next_socket:
mov ebx, [ebx + SOCKET.NextPtr]
or ebx, ebx
jz .error
cmp ebx, eax
jne .next_socket
;cmp [ebx + SOCKET.PID], ecx
;jne .next_socket
ret
 
.error:
xor eax, eax
ret
endp
 
;***************************************************************************
; Function
; is_localport_unused
140,51 → 253,26
; On return, eax = 1 for free, 0 for in use
;
;***************************************************************************
is_localport_unused:
mov al, bh
mov ah, bl
mov bx, ax
proc is_localport_unused stdcall
 
mov edx, SOCKETBUFFSIZE * NUM_SOCKETS
mov ecx, NUM_SOCKETS
mov eax, 0 ; Assume the return value is 'in use'
xchg bl, bh
 
ilu1:
sub edx, SOCKETBUFFSIZE
cmp [edx + sockets + SOCKET.LocalPort], bx
loopnz ilu1 ; Return back if the socket is occupied
xor eax, eax ; Assume the return value is 'free'
inc al
mov edx, net_sockets
 
jz ilu_exit
inc eax ; return port not in use
.next_socket:
mov edx, [edx + SOCKET.NextPtr]
or edx, edx
jz .exit
cmp [edx + SOCKET.LocalPort], bx
jne .next_socket ; Return back if the port is not occupied
 
ilu_exit:
ret
dec al ; return 'in use'
 
 
 
;***************************************************************************
; Function
; get_free_socket
;
; Description
;
;***************************************************************************
get_free_socket:
push ecx
mov eax, SOCKETBUFFSIZE * NUM_SOCKETS
mov ecx, NUM_SOCKETS
 
gfs1:
sub eax, SOCKETBUFFSIZE
cmp [eax + sockets + SOCKET.Status], dword SOCK_EMPTY
loopnz gfs1 ; Return back if the socket is occupied
mov eax, ecx
pop ecx
jz gfs_exit
mov eax, 0xFFFFFFFF
 
gfs_exit:
.exit:
ret
endp
 
 
;***************************************************************************
199,18 → 287,16
; return socket # in eax, -1 if none available
;
;***************************************************************************
socket_open:
call get_free_socket
proc socket_open stdcall
call net_socket_alloc
or eax, eax
jz .error
 
cmp eax, 0xFFFFFFFF
jz so_exit
DEBUGF 1, "K : socket_open (0x%x)\n", eax
 
; ax holds the socket number that is free. Get real address
push eax
Index2RealAddr eax
 
mov [eax + SOCKET.Status], dword SOCK_OPEN
 
mov [eax + SOCKET.Status], SOCK_OPEN
xchg bh, bl
mov [eax + SOCKET.LocalPort], bx
xchg ch, cl
219,18 → 305,18
mov ebx, [stack_ip]
mov [eax + SOCKET.LocalIP], ebx
mov [eax + SOCKET.RemoteIP], edx
mov [eax + SOCKET.rxDataCount], dword 0 ; recieved data count
 
mov esi, [TASK_BASE]
mov ebx, [esi+TASKDATA.pid]
mov [eax + SOCKET.PID], ebx ; save the process ID
pop eax ; Get the socket number back, so we can return it
;pop eax ; Get the socket number back, so we can return it
stdcall net_socket_addr_to_num
ret
 
so_exit:
.error:
DEBUGF 1, "K : socket_open (fail)\n"
or eax, -1
ret
endp
 
 
 
;***************************************************************************
; Function
; socket_open_tcp
245,94 → 331,111
; return socket # in eax, -1 if none available
;
;***************************************************************************
socket_open_tcp:
call get_free_socket
proc socket_open_tcp stdcall
local sockAddr dd ?
 
cmp eax, 0xFFFFFFFF
jz so_exit
cmp esi, SOCKET_PASSIVE
jne .skip_port_check
 
; ax holds the socket number that is free. Get real address
push eax
Index2RealAddr eax
push ebx
mov eax, ebx
xchg al, ah
mov ebx, net_sockets
 
mov [sktAddr], eax
mov [eax], dword SOCK_OPEN
.next_socket:
mov ebx, [ebx + SOCKET.NextPtr]
or ebx, ebx
jz .last_socket
cmp [ebx + SOCKET.TCBState], TCB_LISTEN
jne .next_socket
cmp [ebx + SOCKET.LocalPort], ax
jne .next_socket
 
xchg al, ah
DEBUGF 1, "K : error: port %u is listened by 0x%x\n", ax, ebx
pop ebx
jmp .error
 
.last_socket:
pop ebx
 
.skip_port_check:
call net_socket_alloc
or eax, eax
jz .error
 
DEBUGF 1, "K : socket_open_tcp (0x%x)\n", eax
 
mov [sockAddr], eax
 
; TODO - check this works!
mov [eax + SOCKET.wndsizeTimer], dword 0 ; Reset the window timer.
;xxx: already 0 (intialized by net_socket_alloc)
;mov [eax + SOCKET.wndsizeTimer], 0 ; Reset the window timer.
 
xchg bh, bl
mov [eax + SOCKET.LocalPort], bx
; mov [eax + 12], byte bh ; Local port ( LS 16 bits )
; mov [eax + 13], byte bl ; Local port ( LS 16 bits )
 
xchg ch, cl
mov [eax + SOCKET.RemotePort], cx
; mov [eax + 20], ch ; Remote Port ( LS 16 bits )
; mov [eax + 21], cl ; Remote Port ( LS 16 bits )
 
mov [eax + SOCKET.OrigRemotePort], cx
mov ebx, [stack_ip]
mov [eax + SOCKET.LocalIP], ebx
mov [eax + SOCKET.RemoteIP], edx
mov [eax + SOCKET.rxDataCount], dword 0
mov [eax + SOCKET.OrigRemoteIP], edx
 
; Now fill in TCB state
mov ebx, TCB_LISTEN
cmp esi, SOCKET_PASSIVE
jz sot_001
je @f
mov ebx, TCB_SYN_SENT
@@: mov [eax + SOCKET.TCBState], ebx ; Indicate the state of the TCB
 
sot_001:
mov [eax + SOCKET.TCBState], ebx ; Indicate the state of the TCB
 
mov esi, [TASK_BASE]
mov ecx, [esi+TASKDATA.pid]
mov [eax + SOCKET.PID], ecx ; save the process ID
 
cmp ebx, TCB_LISTEN
je sot_done
je .exit
 
; Now, if we are in active mode, then we have to send a SYN to the specified remote port
mov eax, EMPTY_QUEUE
call dequeue
cmp ax, NO_BUFFER
je sot_done
je .exit
 
push eax
 
mov bl, 0x02 ; SYN
mov ecx, 0
mov bl, TH_SYN
xor ecx, ecx
stdcall build_tcp_packet, [sockAddr]
 
call buildTCPPacket
 
mov eax, NET1OUT_QUEUE
 
mov edx, [stack_ip]
mov ecx, [sktAddr ]
mov ecx, [ecx + 16]
cmp edx, ecx
jne sot_notlocal
mov ecx, [sockAddr]
cmp edx, [ecx + SOCKET.RemoteIP]
jne .not_local
mov eax, IPIN_QUEUE
 
sot_notlocal:
.not_local:
; Send it.
pop ebx
call queue
 
mov esi, [sktAddr]
mov esi, [sockAddr]
 
; increment SND.NXT in socket
add esi, 48
add esi, SOCKET.SND_NXT
call inc_inet_esi
 
sot_done:
pop eax ; Get the socket number back, so we can return it
.exit:
mov ebx, [sockAddr]
mov [ebx + SOCKET.Status], SOCK_OPEN
;pop eax ; Get the socket number back, so we can return it
stdcall net_socket_addr_to_num, ebx
ret
 
sot_exit:
.error:
DEBUGF 1, "K : socket_open_tcp (fail)\n"
or eax, -1
ret
endp
 
 
 
;***************************************************************************
; Function
; socket_close
342,26 → 445,33
; returns 0 for ok, -1 for socket not open (fail)
;
;***************************************************************************
socket_close:
mov eax, 0xFFFFFFFF ; assume this operation will fail..
cmp ebx, NUM_SOCKETS
jae sc_exit
Index2RealAddr ebx
cmp [ebx + SOCKET.Status], dword SOCK_EMPTY
jz sc_exit
proc socket_close stdcall
DEBUGF 1, "K : socket_close (0x%x)\n", ebx
stdcall net_socket_num_to_addr, ebx
or eax, eax
jz .error
 
cmp [eax + SOCKET.Status], dword SOCK_EMPTY
jz .error
 
; Clear the socket varaibles
stdcall net_socket_free, eax
; mov edi, eax
; xor eax, eax
; mov ecx, SOCKETHEADERSIZE
; cld
; rep stosb
 
xor eax, eax
mov edi, ebx
mov ecx, SOCKETHEADERSIZE
cld
rep stosb
ret
 
sc_exit:
.error:
DEBUGF 1, "K : socket_close (fail)\n"
or eax, -1
ret
endp
 
 
 
;***************************************************************************
; Function
; socket_close_tcp
371,7 → 481,9
; returns 0 for ok, -1 for socket not open (fail)
;
;***************************************************************************
socket_close_tcp:
proc socket_close_tcp stdcall
local sockAddr dd ?
DEBUGF 1, "K : socket_close_tcp (0x%x)\n", ebx
; first, remove any resend entries
pusha
 
378,105 → 490,113
mov esi, resendQ
mov ecx, 0
 
sct001:
.next_resendq:
cmp ecx, NUMRESENDENTRIES
je sct003 ; None left
cmp [esi], bl
je sct002 ; found one
je .last_resendq ; None left
;cmp [esi], bl ; XTODO: bl -> ebx
cmp [esi + 4], ebx
je @f ; found one
inc ecx
add esi, 4
jmp sct001
add esi, 8
jmp .next_resendq
 
sct002:
;@@: mov byte[esi], 0xff ; XTODO: 0xff -> 0
@@: mov dword[esi + 4], 0
inc ecx
add esi, 8
jmp .next_resendq
 
mov [esi], byte 0xFF
jmp sct001
 
sct003:
.last_resendq:
popa
 
Index2RealAddr ebx
mov [sktAddr], ebx
mov eax, 0xFFFFFFFF ; assume this operation will fail..
cmp [ebx + SOCKET.Status], dword SOCK_EMPTY
jz sct_exit
stdcall net_socket_num_to_addr, ebx
or eax, eax
jz .error
 
mov ebx, eax
mov [sockAddr], eax
cmp [ebx + SOCKET.Status], SOCK_EMPTY
je .error
 
cmp [ebx + SOCKET.TCBState], TCB_LISTEN ;xxx
je .destroy_tcb ;xxx
cmp [ebx + SOCKET.TCBState], TCB_SYN_SENT ;xxx
je .destroy_tcb ;xxx
 
; Now construct the response, and queue for sending by IP
mov eax, EMPTY_QUEUE
call dequeue
cmp ax, NO_BUFFER
je stl_exit
je .error
 
push eax
 
mov bl, 0x11 ; FIN + ACK
mov ecx, 0
mov esi, 0
;xxx mov bl, TH_FIN + TH_ACK
mov bl, TH_FIN ;xxx
xor ecx, ecx
xor esi, esi
stdcall build_tcp_packet, [sockAddr]
 
call buildTCPPacket
 
mov ebx, [sktAddr]
 
mov ebx, [sockAddr]
; increament SND.NXT in socket
mov esi, 48
add esi, ebx
lea esi, [ebx + SOCKET.SND_NXT]
call inc_inet_esi
 
 
; Get the socket state
mov eax, [ebx + SOCKET.TCBState]
cmp eax, TCB_LISTEN
je destroyTCB
cmp eax, TCB_SYN_SENT
je destroyTCB
;xxx cmp eax, TCB_LISTEN
;xxx je .destroy_tcb
;xxx cmp eax, TCB_SYN_SENT
;xxx je .destroy_tcb
cmp eax, TCB_SYN_RECEIVED
je sct_finwait1
je .fin_wait_1
cmp eax, TCB_ESTABLISHED
je sct_finwait1
je .fin_wait_1
 
; assume CLOSE WAIT
; Send a fin, then enter last-ack state
mov eax, TCB_LAST_ACK
mov [ebx + SOCKET.TCBState], eax
xor eax, eax
jmp sct_send
; TODO: check if it's really a TCB_CLOSE_WAIT
mov [ebx + SOCKET.TCBState], TCB_LAST_ACK
jmp .send
 
sct_finwait1:
.fin_wait_1:
; Send a fin, then enter finwait2 state
mov eax, TCB_FIN_WAIT_1
mov [ebx + SOCKET.TCBState], eax
xor eax, eax
mov [ebx + SOCKET.TCBState], TCB_FIN_WAIT_1
 
sct_send:
.send:
mov eax, NET1OUT_QUEUE
 
mov edx, [stack_ip]
mov ecx, [sktAddr ]
mov ecx, [ecx + 16]
cmp edx, ecx
jne sct_notlocal
mov ecx, [sockAddr]
cmp edx, [ecx + SOCKET.RemoteIP]
jne .not_local
mov eax, IPIN_QUEUE
 
sct_notlocal:
.not_local:
; Send it.
pop ebx
call queue
jmp sct_exit
jmp .exit
 
destroyTCB:
pop eax
; Clear the socket varaibles
.destroy_tcb:
;xxx pop eax
 
; Clear the socket variables
;xxx stdcall net_socket_free, [sockAddr]
stdcall net_socket_free, ebx
 
.exit:
xor eax, eax
mov edi, ebx
mov ecx, SOCKETHEADERSIZE
cld
rep stosb
ret
 
sct_exit:
.error:
DEBUGF 1, "K : socket_close_tcp (fail)\n"
or eax, -1
ret
endp
 
 
 
;***************************************************************************
; Function
; socket_poll
486,12 → 606,20
; returns count in eax.
;
;***************************************************************************
socket_poll:
Index2RealAddr ebx
mov eax, [ebx + SOCKET.rxDataCount]
proc socket_poll stdcall
; DEBUGF 1, "socket_poll(0x%x)\n", ebx
stdcall net_socket_num_to_addr, ebx
or eax, eax
jz .error
 
mov eax, [eax + SOCKET.rxDataCount]
ret
 
.error:
;or eax, -1
xor eax, eax
ret
endp
 
 
;***************************************************************************
503,14 → 631,27
; returns TCB state in eax.
;
;***************************************************************************
socket_status:
Index2RealAddr ebx
mov eax, [ebx + SOCKET.TCBState]
proc socket_status stdcall
;; DEBUGF 1, "socket_status(0x%x)\n", ebx
stdcall net_socket_num_to_addr, ebx
or eax, eax
jz .error
 
mov eax, [eax + SOCKET.TCBState]
ret
 
.error:
;or eax, -1
xor eax, eax
ret
endp
 
; Index2RealAddr ebx
; mov eax, [ebx + SOCKET.TCBState]
;
; ret
 
 
;***************************************************************************
; Function
; socket_read
520,12 → 661,16
; returns # of bytes remaining in eax, data in bl
;
;***************************************************************************
socket_read:
Index2RealAddr ebx
proc socket_read stdcall
; DEBUGF 1, "socket_read(0x%x)\n", ebx
stdcall net_socket_num_to_addr, ebx
or eax, eax
jz .error
 
mov ebx, eax
mov eax, [ebx + SOCKET.rxDataCount] ; get count of bytes
mov ecx, 1
test eax, eax
jz sr2
jz .error
 
dec eax
mov esi, ebx ; esi is address of socket
537,18 → 682,19
inc esi
 
mov ecx, (SOCKETBUFFSIZE - SOCKETHEADERSIZE) / 4
lea edi, [ebx + SOCKETHEADERSIZE]
lea esi, [edi + 1]
cld
rep movsd
xor ecx, ecx
 
sr1:
jmp sor_exit
ret
 
sr2:
xor bl, bl
 
sor_exit:
.error:
;or eax, -1
xor eax, eax
xor ebx, ebx
ret
endp
 
 
;***************************************************************************
562,22 → 708,27
; returns # of bytes copied in eax
;
;***************************************************************************
socket_read_packet:
Index2RealAddr ebx ; get real socket address
proc socket_read_packet stdcall
; DEBUGF 1, "socket_read_packet(0x%x)\n", ebx
stdcall net_socket_num_to_addr, ebx ; get real socket address
or eax, eax
jz .error
 
mov ebx, eax
mov eax, [ebx + SOCKET.rxDataCount] ; get count of bytes
test eax, eax ; if count of bytes is zero..
jz .exit ; exit function (eax will be zero)
 
test edx, edx ; if buffer size is zero, copy all data
jz .copyallbytes
jz .copy_all_bytes
cmp edx, eax ; if buffer size is larger then the bytes of data, copy all data
jge .copyallbytes
jge .copy_all_bytes
 
sub eax, edx ; store new count (data bytes in buffer - bytes we're about to copy)
mov [ebx + SOCKET.rxDataCount], eax ;
push eax
mov eax, edx ; number of bytes we want to copy must be in eax
call .startcopy ; copy to the application
call .start_copy ; copy to the application
 
mov esi, ebx ; now we're going to copy the remaining bytes to the beginning
add esi, SOCKETHEADERSIZE ; we dont need to copy the header
592,33 → 743,36
and ecx, 3
rep movsb ; copy remaining bytes
 
.exit:
ret ; at last, exit
 
.copyallbytes:
.error:
;or eax, -1
xor eax, eax
ret
 
.copy_all_bytes:
xor esi, esi
mov [ebx + SOCKET.rxDataCount], esi ; store new count (zero)
call .start_copy
ret
 
.startcopy:
mov edi, ecx ;
; add edi, std_application_base_address ; get data pointer to buffer in application
 
mov esi, ebx ;
.start_copy:
mov edi, ecx
mov esi, ebx
add esi, SOCKETHEADERSIZE ; we dont need to copy the header
mov ecx, eax ; eax is count of bytes
push ecx
shr ecx, 2 ; divide eax by 4
cld ; copy all full dwords
rep movsd ;
rep movsd
pop ecx
and ecx, 3
rep movsb ; copy the rest bytes
retn ; exit, or go back to shift remaining bytes if any
endp
 
.exit:
ret ; exit, or go back to shift remaining bytes if any
 
 
 
 
;***************************************************************************
; Function
; socket_write
631,19 → 785,22
; could not queue IP packet )
;
;***************************************************************************
socket_write:
Index2RealAddr ebx
proc socket_write stdcall
; DEBUGF 1, "socket_write(0x%x)\n", ebx
stdcall net_socket_num_to_addr, ebx ; get real socket address
or eax, eax
jz .error
 
mov eax, 0xFFFFFFFF
mov ebx, eax
 
; If the socket is invalid, return with an error code
cmp [ebx], dword SOCK_EMPTY
je sw_exit
cmp [ebx + SOCKET.Status], SOCK_EMPTY
je .error
 
 
mov eax, EMPTY_QUEUE
call dequeue
cmp ax, NO_BUFFER
je sw_exit
je .error
 
; Save the queue entry number
push eax
662,55 → 819,46
; So, ebx holds the socket ptr, edx holds the IPbuffer ptr
 
; Fill in the IP header ( some data is in the socket descriptor)
mov eax, [ebx + 8]
mov [edx + 12], eax ; source IP
mov eax, [ebx + 16]
mov [edx + 16], eax ; Destination IP
mov eax, [ebx + SOCKET.LocalIP]
mov [edx + IP_PACKET.SourceAddress], eax
mov eax, [ebx + SOCKET.RemoteIP]
mov [edx + IP_PACKET.DestinationAddress], eax
 
mov al, 0x45
mov [edx], al ; Version, IHL
xor al, al
mov [edx + 1], al ; Type of service
mov [edx + IP_PACKET.VersionAndIHL], 0x45
mov [edx + IP_PACKET.TypeOfService], 0
 
pop eax ; Get the UDP data length
push eax
 
add eax, 20 + 8 ; add IP header and UDP header lengths
mov [edx + 2], ah
mov [edx + 3], al
xor al, al
mov [edx + 4], al
mov [edx + 5], al
mov al, 0x40
mov [edx + 6], al
xor al, al
mov [edx + 7], al
mov al, 0x20
mov [edx + 8], al
mov al, 17
mov [edx + 9], al
xchg al, ah
mov [edx + IP_PACKET.TotalLength], ax
xor eax, eax
mov [edx + IP_PACKET.Identification], ax
mov [edx + IP_PACKET.FlagsAndFragmentOffset], 0x0040
mov [edx + IP_PACKET.TimeToLive], 0x20
mov [edx + IP_PACKET.Protocol], PROTOCOL_UDP
 
; Checksum left unfilled
xor ax, ax
mov [edx + 10], ax
mov [edx + IP_PACKET.HeaderChecksum], ax
 
; Fill in the UDP header ( some data is in the socket descriptor)
mov ax, [ebx + 12]
mov [edx + 20], ax
mov ax, [ebx + SOCKET.LocalPort]
mov [edx + 20 + UDP_PACKET.SourcePort], ax
 
mov ax, [ebx + 20]
mov [edx + 20 + 2], ax
mov ax, [ebx + SOCKET.RemotePort]
mov [edx + 20 + UDP_PACKET.DestinationPort], ax
 
pop eax
push eax
 
add eax, 8
mov [edx + 20 + 4], ah
mov [edx + 20 + 5], al
xchg al, ah
mov [edx + 20 + UDP_PACKET.Length], ax
 
; Checksum left unfilled
xor ax, ax
mov [edx + 20 + 6], ax
xor eax, eax
mov [edx + 20 + UDP_PACKET.Checksum], ax
 
pop ecx ; count of bytes to send
mov ebx, ecx ; need the length later
730,16 → 878,15
; we have edx as IPbuffer ptr.
; Fill in the UDP checksum
; First, fill in pseudoheader
mov eax, [edx + 12]
mov eax, [edx + IP_PACKET.SourceAddress]
mov [pseudoHeader], eax
mov eax, [edx + 16]
mov eax, [edx + IP_PACKET.DestinationAddress]
mov [pseudoHeader+4], eax
mov ax, 0x1100 ; 0 + protocol
mov [pseudoHeader+8], ax
mov word[pseudoHeader + 8], PROTOCOL_UDP shl 8 + 0 ; 0 + protocol
add ebx, 8
mov eax, ebx
mov [pseudoHeader+10], ah
mov [pseudoHeader+11], al
xchg al, ah
mov [pseudoHeader + 10], ax
 
mov eax, pseudoHeader
mov [checkAdd1], eax
757,44 → 904,43
 
; If the UDP checksum computes to 0, we must make it 0xffff
; (0 is reserved for 'not used')
cmp ax, 0
jne sw_001
test ax, ax
jnz @f
mov ax, 0xffff
 
sw_001:
mov [edx + 20 + 6], ah
mov [edx + 20 + 7], al
@@: xchg al, ah
mov [edx + 20 + UDP_PACKET.Checksum], ax
 
; Fill in the IP header checksum
GET_IHL ecx,edx ; get IP-Header length
stdcall checksum_jb,edx,ecx ; buf_ptr, buf_size
xchg al, ah
mov [edx + IP_PACKET.HeaderChecksum], ax
 
mov [edx + 10], ah
mov [edx + 11], al
 
; Check destination IP address.
; If it is the local host IP, route it back to IP_RX
 
pop ebx
mov eax, NET1OUT_QUEUE
 
mov ecx, [ edx + 16]
mov ecx, [edx + SOCKET.RemoteIP]
mov edx, [stack_ip]
cmp edx, ecx
jne sw_notlocal
jne .not_local
mov eax, IPIN_QUEUE
 
sw_notlocal:
.not_local:
; Send it.
call queue
 
xor eax, eax
ret
 
sw_exit:
.error:
or eax, -1
ret
endp
 
 
 
;***************************************************************************
; Function
; socket_write_tcp
807,30 → 953,33
; could not queue IP packet )
;
;***************************************************************************
socket_write_tcp:
Index2RealAddr ebx
proc socket_write_tcp stdcall
local sockAddr dd ?
 
mov [sktAddr], ebx
; DEBUGF 1, "socket_write_tcp(0x%x)\n", ebx
stdcall net_socket_num_to_addr, ebx
or eax, eax
jz .error
 
mov eax, 0xFFFFFFFF
mov ebx, eax
mov [sockAddr], ebx
 
; If the socket is invalid, return with an error code
cmp [ebx], dword SOCK_EMPTY
je swt_exit
cmp [ebx + SOCKET.Status], SOCK_EMPTY
je .error
 
; If the sockets window timer is nonzero, do not queue packet
; TODO - done
cmp [ebx + SOCKET.wndsizeTimer], dword 0
jne swt_exit
cmp [ebx + SOCKET.wndsizeTimer], 0
jne .error
 
mov eax, EMPTY_QUEUE
call dequeue
cmp ax, NO_BUFFER
je swt_exit
je .error
 
push eax
 
mov bl, 0x10 ; ACK
 
; Get the address of the callers data
mov edi, [TASK_BASE]
add edi, TASKDATA.mem_start
841,7 → 990,8
push eax
 
push ecx
call buildTCPPacket
mov bl, TH_ACK
stdcall build_tcp_packet, [sockAddr]
pop ecx
 
; Check destination IP address.
852,13 → 1002,12
mov eax, NET1OUT_QUEUE
 
mov edx, [stack_ip]
mov ecx, [sktAddr ]
mov ecx, [ecx + 16]
cmp edx, ecx
jne swt_notlocal
mov ecx, [sockAddr]
cmp edx, [ecx + SOCKET.RemoteIP]
jne .not_local
mov eax, IPIN_QUEUE
 
swt_notlocal:
.not_local:
pop ecx
 
push ebx ; save ipbuffer number
865,11 → 1014,11
 
call queue
 
mov esi, [sktAddr]
mov esi, [sockAddr]
 
; increament SND.NXT in socket
; Amount to increment by is in ecx
add esi, 48
add esi, SOCKET.SND_NXT
call add_inet_esi
 
pop ebx
879,17 → 1028,17
mov esi, resendQ
mov ecx, 0
 
swt003:
.next_resendq:
cmp ecx, NUMRESENDENTRIES
je swt001 ; None found
cmp [esi], byte 0xFF
je swt002 ; found one
je .exit ; None found
;cmp byte[esi], 0xff ; XTODO: 0xff -> 0
cmp dword[esi + 4], 0
je @f ; found one
inc ecx
add esi, 4
jmp swt003
add esi, 8
jmp .next_resendq
 
swt002:
push ebx
@@: push ebx
 
; OK, we have a buffer descriptor ptr in esi.
; resend entry # in ecx
899,20 → 1048,19
; retry time
; fill IP buffer associated with this descriptor
 
mov eax, [sktAddr]
sub eax, sockets
shr eax, 12 ; get skt #
mov [esi], al
mov [esi + 1], byte TCP_RETRIES
mov [esi + 2], word TCP_TIMEOUT
stdcall net_socket_addr_to_num, [sockAddr]
;mov [esi], al ; XTODO: al -> eax
mov [esi + 4], eax
mov byte[esi + 1], TCP_RETRIES
mov word[esi + 2], TCP_TIMEOUT
 
inc ecx
; Now get buffer location, and copy buffer across. argh! more copying,,
mov edi, resendBuffer - IPBUFFSIZE
swt002a:
add edi, IPBUFFSIZE
loop swt002a
 
@@: add edi, IPBUFFSIZE
loop @b
 
; we have dest buffer location in edi
pop eax
; convert source buffer pointer eax to the absolute address
926,9 → 1074,11
cld
rep movsb
 
swt001:
.exit:
xor eax, eax
ret
 
swt_exit:
.error:
or eax, -1
ret
 
endp