Subversion Repositories Kolibri OS

Compare Revisions

Regard whitespace Rev 1248 → Rev 1249

/kernel/branches/net/network/udp.inc
75,8 → 75,34
UDP_handler:
 
DEBUGF 1,"UDP_Handler\n"
; TODO: First validate the header & checksum!
; First validate, checksum:
 
DEBUGF 1,"Real UDP checksum: %x\n", [edx + UDP_Packet.Checksum]:4
mov [edx + UDP_Packet.Checksum], 0
 
pusha
 
rol cx, 8
push cx
rol cx, 8
push word IP_PROTO_UDP shl 8
push edi
push esi
 
mov esi, edx
xor edx, edx
call checksum_1
; Checksum for pseudoheader
mov ecx, 12
mov esi, esp
call checksum_1
add esp, 12
call checksum_2
 
popa
 
 
 
; Look for a socket where
; IP Packet UDP Destination Port = local Port
; IP Packet SA = Remote IP
85,14 → 111,14
.try_more:
mov bx , [edx + UDP_Packet.DestinationPort] ; get the local port from the IP Packet's UDP header
.next_socket:
mov eax, [eax + SOCKET.NextPtr]
mov eax, [eax + SOCKET_head.NextPtr]
or eax, eax
jz .dump
cmp [eax + SOCKET.Domain], AF_INET4
cmp [eax + SOCKET_head.Domain], AF_INET4
jne .next_socket
cmp [eax + SOCKET.Type], IP_PROTO_UDP
cmp [eax + SOCKET_head.Type], IP_PROTO_UDP
jne .next_socket
cmp [eax + SOCKET.LocalPort], bx
cmp [eax + SOCKET_head.end + IPv4_SOCKET.end + UDP_SOCKET.LocalPort], bx
jne .next_socket
 
DEBUGF 1,"found socket with matching domain, type and localport\n"
101,12 → 127,12
; I will accept the first incoming response to be the one
; I bind to, if the socket is opened with a destination IP address of
; 255.255.255.255
cmp [eax + SOCKET.RemoteIP], 0xffffffff
cmp [eax + SOCKET_head.end + IPv4_SOCKET.RemoteIP], 0xffffffff
je .ok1
 
mov ebx, [esp]
mov ebx, [ebx + ETH_FRAME.Data + IPv4_Packet.SourceAddress] ; get the Source address from the IP Packet FIXME
cmp [eax + SOCKET.RemoteIP], ebx
cmp [eax + SOCKET_head.end + IPv4_SOCKET.RemoteIP], ebx
jne .try_more ; Quit if the source IP is not valid, check for more sockets with this IP/PORT combination
 
 
115,10 → 141,10
 
mov bx, [edx + UDP_Packet.SourcePort] ; Remote port must be 0, or equal to sourceport of packet
 
cmp [eax + SOCKET.RemotePort], 0
cmp [eax + SOCKET_head.end + IPv4_SOCKET.end + UDP_SOCKET.RemotePort], 0
je .ok2
 
cmp [eax + SOCKET.RemotePort], bx
cmp [eax + SOCKET_head.end + IPv4_SOCKET.end + UDP_SOCKET.RemotePort], bx
jne .dump
 
.ok2:
130,10 → 156,21
sub cx , UDP_Packet.Data
mov dx , bx
 
call socket_internal_receiver
 
lea ebx, [eax + SOCKET_head.lock]
call wait_mutex
mov [eax + SOCKET_head.end + IPv4_SOCKET.end + UDP_SOCKET.RemotePort], dx ; update remote port number
mov [eax + SOCKET_head.end + IPv4_SOCKET.RemoteIP], edi
inc [UDP_PACKETS_RX]
 
pop edi
add esp, 4
 
sub esi, edi
xchg esi, edi
jmp socket_internal_receiver
 
 
.dump:
DEBUGF 1,"Dumping UDP packet\n"
call kernel_free
146,69 → 183,93
 
;-----------------------------------------------------------------
;
; Note: UDP works only on top of IP protocol :)
; UDP_socket_send
;
; IN: eax = dest ip
; ebx = source ip
; ecx = data length
; edx = remote port shl 16 + local port (both in INET order)
; esi = data offset
; IN: eax = socket pointer
; ecx = number of bytes to send
; esi = pointer to data
;
;-----------------------------------------------------------------
 
UDP_create_packet:
align 4
UDP_socket_send:
 
mov edx, dword [eax + SOCKET_head.end + IPv4_SOCKET.end + UDP_SOCKET.LocalPort] ; load local port and remote port at once
DEBUGF 1,"local port: %x, remote port: %x\n",\
[eax + SOCKET_head.end + IPv4_SOCKET.end + UDP_SOCKET.LocalPort]:4,\
[eax + SOCKET_head.end + IPv4_SOCKET.end + UDP_SOCKET.RemotePort]:4
mov ebx, [eax + SOCKET_head.end + IPv4_SOCKET.LocalIP]
mov eax, [eax + SOCKET_head.end + IPv4_SOCKET.RemoteIP]
 
DEBUGF 1,"Create UDP Packet (size=%u)\n",ecx
 
push edx esi
mov di , IP_PROTO_UDP
 
sub esp, 8 ; reserve some place in stack for later
 
; Create the pseudoheader in stack,
; (now that we still have all the variables that are needed.)
push dword IP_PROTO_UDP shl 8
push eax
push ebx
 
add ecx, UDP_Packet.Data
mov di , IP_PROTO_UDP
 
; dx = fragment id
; TODO: fill in: dx = fragment id
 
push edx esi
call IPv4_create_packet ; TODO: figure out a way to choose between IPv4 and IPv6
cmp edi, -1
je .fail
 
mov byte[edi + UDP_Packet.Length], ch
mov byte[edi + UDP_Packet.Length+1], cl
sub ecx , UDP_Packet.Data
mov [esp + 8 + 12], eax ; pointer to buffer start
mov [esp + 8 + 12 + 4], edx ; buffer size
 
rol cx, 8
mov [edi + UDP_Packet.Length], cx
mov [esp + 8 + 10], cx
ror cx, 8
 
pop esi
push edi
push edi ecx
sub ecx, UDP_Packet.Data
add edi, UDP_Packet.Data
push cx
shr ecx, 2
rep movsd
pop cx
mov ecx, [esp]
and cx , 3
rep movsb
pop edi
pop ecx edi
 
pop ecx
mov dword [edi + UDP_Packet.SourcePort], ecx ; notice: we write both port's at once
pop dword [edi + UDP_Packet.SourcePort] ; fill in both portnumbers
mov [edi + UDP_Packet.Checksum], 0 ; set it to zero, to calculate checksum
 
mov [edi + UDP_Packet.Checksum], 0
; Checksum for UDP header + data
xor edx, edx
mov esi, edi
call checksum_1
; Checksum for pseudoheader
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 UDP header
call checksum_2
mov [edi + UDP_Packet.Checksum], dx
 
; TODO: calculate checksum using Pseudo-header (However, using a 0 as checksum shouldnt generate any errors :)
 
inc [UDP_PACKETS_TX]
 
push edx eax ; TODO: make this work on other protocols besides ethernet
DEBUGF 1,"Sending UDP Packet to device %x\n", ebx ;
jmp ETH_Sender ;
jmp ETH_sender ;
 
.exit:
ret
 
.fail:
; todo: queue the packet
add esp, 8
add esp, 8+12+8
ret
 
 
 
 
;---------------------------------------------------------------------------
;
; UDP_API