Rev 7682 | Only display areas with differences | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 7682 | Rev 9739 | ||
---|---|---|---|
1 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
1 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
2 | ;; ;; |
2 | ;; ;; |
3 | ;; Copyright (C) KolibriOS team 2004-2019. All rights reserved. ;; |
3 | ;; Copyright (C) KolibriOS team 2004-2019. All rights reserved. ;; |
4 | ;; Distributed under terms of the GNU General Public License ;; |
4 | ;; Distributed under terms of the GNU General Public License ;; |
5 | ;; ;; |
5 | ;; ;; |
6 | ;; UDP.INC ;; |
6 | ;; UDP.INC ;; |
7 | ;; ;; |
7 | ;; ;; |
8 | ;; Part of the TCP/IP network stack for KolibriOS ;; |
8 | ;; Part of the TCP/IP network stack for KolibriOS ;; |
9 | ;; ;; |
9 | ;; ;; |
10 | ;; Written by hidnplayr@kolibrios.org ;; |
10 | ;; Written by hidnplayr@kolibrios.org ;; |
11 | ;; ;; |
11 | ;; ;; |
12 | ;; GNU GENERAL PUBLIC LICENSE ;; |
12 | ;; GNU GENERAL PUBLIC LICENSE ;; |
13 | ;; Version 2, June 1991 ;; |
13 | ;; Version 2, June 1991 ;; |
14 | ;; ;; |
14 | ;; ;; |
15 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
15 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
16 | 16 | ||
17 | $Revision: 7682 $ |
17 | $Revision: 9739 $ |
18 | 18 | ||
19 | 19 | ||
20 | struct UDP_header |
20 | struct UDP_header |
21 | 21 | ||
22 | SourcePort dw ? |
22 | SourcePort dw ? |
23 | DestinationPort dw ? |
23 | DestinationPort dw ? |
24 | Length dw ? ; Length of (UDP Header + Data) |
24 | Length dw ? ; Length of (UDP Header + Data) |
25 | Checksum dw ? |
25 | Checksum dw ? |
26 | 26 | ||
27 | ends |
27 | ends |
28 | 28 | ||
29 | 29 | ||
30 | uglobal |
30 | uglobal |
31 | align 4 |
31 | align 4 |
32 | 32 | ||
33 | UDP_packets_tx rd NET_DEVICES_MAX |
33 | UDP_packets_tx rd NET_DEVICES_MAX |
34 | UDP_packets_rx rd NET_DEVICES_MAX |
34 | UDP_packets_rx rd NET_DEVICES_MAX |
35 | 35 | ||
36 | endg |
36 | endg |
37 | 37 | ||
38 | 38 | ||
39 | ;-----------------------------------------------------------------; |
39 | ;-----------------------------------------------------------------; |
40 | ; ; |
40 | ; ; |
41 | ; udp_init: This function resets all UDP variables ; |
41 | ; udp_init: This function resets all UDP variables ; |
42 | ; ; |
42 | ; ; |
43 | ;-----------------------------------------------------------------; |
43 | ;-----------------------------------------------------------------; |
44 | macro udp_init { |
44 | macro udp_init { |
45 | 45 | ||
46 | xor eax, eax |
46 | xor eax, eax |
47 | mov edi, UDP_packets_tx |
47 | mov edi, UDP_packets_tx |
48 | mov ecx, 2*NET_DEVICES_MAX |
48 | mov ecx, 2*NET_DEVICES_MAX |
49 | rep stosd |
49 | rep stosd |
50 | } |
50 | } |
51 | 51 | ||
52 | 52 | ||
53 | macro udp_checksum IP1, IP2 { ; esi = ptr to udp packet, ecx = packet size, destroys: ecx, edx |
53 | macro udp_checksum IP1, IP2 { ; esi = ptr to udp packet, ecx = packet size, destroys: ecx, edx |
54 | 54 | ||
55 | ; Pseudoheader |
55 | ; Pseudoheader |
56 | mov edx, IP_PROTO_UDP |
56 | mov edx, IP_PROTO_UDP |
57 | 57 | ||
58 | add dl, byte[IP1+1] |
58 | add dl, byte[IP1+1] |
59 | adc dh, byte[IP1+0] |
59 | adc dh, byte[IP1+0] |
60 | adc dl, byte[IP1+3] |
60 | adc dl, byte[IP1+3] |
61 | adc dh, byte[IP1+2] |
61 | adc dh, byte[IP1+2] |
62 | 62 | ||
63 | adc dl, byte[IP2+1] |
63 | adc dl, byte[IP2+1] |
64 | adc dh, byte[IP2+0] |
64 | adc dh, byte[IP2+0] |
65 | adc dl, byte[IP2+3] |
65 | adc dl, byte[IP2+3] |
66 | adc dh, byte[IP2+2] |
66 | adc dh, byte[IP2+2] |
67 | 67 | ||
68 | adc dl, cl ; byte[esi+UDP_header.Length+1] |
68 | adc dl, cl ; byte[esi+UDP_header.Length+1] |
69 | adc dh, ch ; byte[esi+UDP_header.Length+0] |
69 | adc dh, ch ; byte[esi+UDP_header.Length+0] |
70 | 70 | ||
71 | ; Done with pseudoheader, now do real header |
71 | ; Done with pseudoheader, now do real header |
72 | adc dl, byte[esi+UDP_header.SourcePort+1] |
72 | adc dl, byte[esi+UDP_header.SourcePort+1] |
73 | adc dh, byte[esi+UDP_header.SourcePort+0] |
73 | adc dh, byte[esi+UDP_header.SourcePort+0] |
74 | 74 | ||
75 | adc dl, byte[esi+UDP_header.DestinationPort+1] |
75 | adc dl, byte[esi+UDP_header.DestinationPort+1] |
76 | adc dh, byte[esi+UDP_header.DestinationPort+0] |
76 | adc dh, byte[esi+UDP_header.DestinationPort+0] |
77 | 77 | ||
78 | adc dl, byte[esi+UDP_header.Length+1] |
78 | adc dl, byte[esi+UDP_header.Length+1] |
79 | adc dh, byte[esi+UDP_header.Length+0] |
79 | adc dh, byte[esi+UDP_header.Length+0] |
80 | 80 | ||
81 | adc edx, 0 |
81 | adc edx, 0 |
82 | 82 | ||
83 | ; Done with header, now do data |
83 | ; Done with header, now do data |
84 | push esi |
84 | push esi |
85 | movzx ecx, [esi+UDP_header.Length] |
85 | movzx ecx, [esi+UDP_header.Length] |
86 | rol cx , 8 |
86 | rol cx , 8 |
87 | sub cx , sizeof.UDP_header |
87 | sub cx , sizeof.UDP_header |
88 | add esi, sizeof.UDP_header |
88 | add esi, sizeof.UDP_header |
89 | 89 | ||
90 | call checksum_1 |
90 | call checksum_1 |
91 | call checksum_2 |
91 | call checksum_2 |
92 | pop esi |
92 | pop esi |
93 | 93 | ||
94 | add [esi+UDP_header.Checksum], dx ; this final instruction will set or clear ZF :) |
94 | add [esi+UDP_header.Checksum], dx ; this final instruction will set or clear ZF :) |
95 | 95 | ||
96 | } |
96 | } |
97 | 97 | ||
98 | 98 | ||
99 | ;-----------------------------------------------------------------; |
99 | ;-----------------------------------------------------------------; |
100 | ; ; |
100 | ; ; |
101 | ; udp_input: Inject the UDP data in the application sockets. ; |
101 | ; udp_input: Inject the UDP data in the application sockets. ; |
102 | ; ; |
102 | ; ; |
103 | ; IN: [esp] = ptr to buffer ; |
103 | ; IN: [esp] = ptr to buffer ; |
104 | ; ebx = ptr to device struct ; |
104 | ; ebx = ptr to device struct ; |
105 | ; ecx = UDP packet size ; |
105 | ; ecx = UDP packet size ; |
106 | ; edx = ptr to IPv4 header ; |
106 | ; edx = ptr to IPv4 header ; |
107 | ; esi = ptr to UDP packet data ; |
107 | ; esi = ptr to UDP packet data ; |
108 | ; edi = interface number*4 ; |
108 | ; edi = interface number*4 ; |
109 | ; ; |
109 | ; ; |
110 | ; OUT: / ; |
110 | ; OUT: / ; |
111 | ; ; |
111 | ; ; |
112 | ;-----------------------------------------------------------------; |
112 | ;-----------------------------------------------------------------; |
113 | align 4 |
113 | align 4 |
114 | udp_input: |
114 | udp_input: |
115 | 115 | ||
116 | DEBUGF DEBUG_NETWORK_VERBOSE, "UDP_input: size=%u\n", ecx |
116 | DEBUGF DEBUG_NETWORK_VERBOSE, "UDP_input: size=%u\n", ecx |
117 | 117 | ||
118 | ; First validate, checksum |
118 | ; First validate, checksum |
119 | 119 | ||
120 | neg [esi + UDP_header.Checksum] ; substract checksum from 0 |
120 | neg [esi + UDP_header.Checksum] ; substract checksum from 0 |
121 | jz .no_checksum ; if checksum is zero, it is considered valid |
121 | jz .no_checksum ; if checksum is zero, it is considered valid |
122 | 122 | ||
123 | ; otherwise, we will re-calculate the checksum and add it to this value, thus creating 0 when it is correct |
123 | ; otherwise, we will re-calculate the checksum and add it to this value, thus creating 0 when it is correct |
124 | 124 | ||
125 | mov eax, edx |
125 | mov eax, edx |
126 | udp_checksum (eax+IPv4_header.SourceAddress), (eax+IPv4_header.DestinationAddress) |
126 | udp_checksum (eax+IPv4_header.SourceAddress), (eax+IPv4_header.DestinationAddress) |
127 | jnz .checksum_mismatch |
127 | jnz .checksum_mismatch |
128 | 128 | ||
129 | .no_checksum: |
129 | .no_checksum: |
130 | DEBUGF DEBUG_NETWORK_VERBOSE, "UDP_input: checksum ok\n" |
130 | DEBUGF DEBUG_NETWORK_VERBOSE, "UDP_input: checksum ok\n" |
131 | 131 | ||
132 | ; Convert length to little endian |
132 | ; Convert length to little endian |
133 | 133 | ||
134 | rol [esi + UDP_header.Length], 8 |
134 | rol [esi + UDP_header.Length], 8 |
135 | 135 | ||
136 | ; Look for a socket where |
136 | ; Look for a socket where |
137 | ; IP Packet UDP Destination Port = local Port |
137 | ; IP Packet UDP Destination Port = local Port |
138 | ; IP Packet SA = Remote IP |
138 | ; IP Packet SA = Remote IP |
139 | 139 | ||
140 | pusha |
140 | pusha |
141 | mov ecx, socket_mutex |
141 | mov ecx, socket_mutex |
142 | call mutex_lock |
142 | call mutex_lock |
143 | popa |
143 | popa |
144 | 144 | ||
145 | mov cx, [esi + UDP_header.SourcePort] |
145 | mov cx, [esi + UDP_header.SourcePort] |
146 | mov dx, [esi + UDP_header.DestinationPort] |
146 | mov dx, [esi + UDP_header.DestinationPort] |
147 | mov eax, net_sockets |
147 | mov eax, net_sockets |
148 | .next_socket: |
148 | .next_socket: |
149 | mov eax, [eax + SOCKET.NextPtr] |
149 | mov eax, [eax + SOCKET.NextPtr] |
150 | or eax, eax |
150 | or eax, eax |
151 | jz .unlock_dump |
151 | jz .unlock_dump |
152 | 152 | ||
153 | cmp [eax + SOCKET.Domain], AF_INET4 |
153 | cmp [eax + SOCKET.Domain], AF_INET4 |
154 | jne .next_socket |
154 | jne .next_socket |
155 | 155 | ||
156 | cmp [eax + SOCKET.Protocol], IP_PROTO_UDP |
156 | cmp [eax + SOCKET.Protocol], IP_PROTO_UDP |
157 | jne .next_socket |
157 | jne .next_socket |
158 | 158 | ||
159 | cmp [eax + UDP_SOCKET.LocalPort], dx |
159 | cmp [eax + UDP_SOCKET.LocalPort], dx |
160 | jne .next_socket |
160 | jne .next_socket |
161 | 161 | ||
162 | DEBUGF DEBUG_NETWORK_VERBOSE, "UDP_input: socket=%x\n", eax |
162 | DEBUGF DEBUG_NETWORK_VERBOSE, "UDP_input: socket=%x\n", eax |
163 | 163 | ||
164 | pusha |
164 | pusha |
165 | mov ecx, socket_mutex |
165 | mov ecx, socket_mutex |
166 | call mutex_unlock |
166 | call mutex_unlock |
167 | popa |
167 | popa |
168 | 168 | ||
169 | ;;; TODO: when packet is processed, check more sockets?! |
169 | ;;; TODO: when packet is processed, check more sockets?! |
170 | 170 | ||
171 | ; FIXME: check remote IP if possible |
171 | ; FIXME: check remote IP if possible |
172 | ; |
172 | ; |
173 | ; cmp [eax + IP_SOCKET.RemoteIP], 0xffffffff |
173 | ; cmp [eax + IP_SOCKET.RemoteIP], 0xffffffff |
174 | ; je @f |
174 | ; je @f |
175 | ; cmp [eax + IP_SOCKET.RemoteIP], |
175 | ; cmp [eax + IP_SOCKET.RemoteIP], |
176 | ; jne .next_socket |
176 | ; jne .next_socket |
177 | ; @@: |
177 | ; @@: |
178 | 178 | ||
179 | cmp [eax + UDP_SOCKET.RemotePort], 0 |
179 | cmp [eax + UDP_SOCKET.RemotePort], 0 |
180 | je .updateport |
180 | je .updateport |
181 | 181 | ||
182 | cmp [eax + UDP_SOCKET.RemotePort], cx |
182 | cmp [eax + UDP_SOCKET.RemotePort], cx |
183 | jne .dump |
183 | jne .dump |
184 | 184 | ||
185 | pusha |
185 | pusha |
186 | lea ecx, [eax + SOCKET.mutex] |
186 | lea ecx, [eax + SOCKET.mutex] |
187 | call mutex_lock |
187 | call mutex_lock |
188 | popa |
188 | popa |
189 | 189 | ||
190 | .updatesock: |
190 | .updatesock: |
191 | inc [UDP_packets_rx + edi] |
191 | inc [UDP_packets_rx + edi] |
192 | 192 | ||
193 | movzx ecx, [esi + UDP_header.Length] |
193 | movzx ecx, [esi + UDP_header.Length] |
194 | sub ecx, sizeof.UDP_header |
194 | sub ecx, sizeof.UDP_header |
195 | add esi, sizeof.UDP_header |
195 | add esi, sizeof.UDP_header |
196 | 196 | ||
197 | jmp socket_input |
197 | jmp socket_input |
198 | 198 | ||
199 | .updateport: |
199 | .updateport: |
200 | pusha |
200 | pusha |
201 | lea ecx, [eax + SOCKET.mutex] |
201 | lea ecx, [eax + SOCKET.mutex] |
202 | call mutex_lock |
202 | call mutex_lock |
203 | popa |
203 | popa |
204 | 204 | ||
205 | DEBUGF DEBUG_NETWORK_VERBOSE, "UDP_input: new remote port=%x\n", cx ; FIXME: find a way to print big endian values with debugf |
205 | DEBUGF DEBUG_NETWORK_VERBOSE, "UDP_input: new remote port=%x\n", cx ; FIXME: find a way to print big endian values with debugf |
206 | mov [eax + UDP_SOCKET.RemotePort], cx |
206 | mov [eax + UDP_SOCKET.RemotePort], cx |
207 | jmp .updatesock |
207 | jmp .updatesock |
208 | 208 | ||
209 | .unlock_dump: |
209 | .unlock_dump: |
210 | pusha |
210 | pusha |
211 | mov ecx, socket_mutex |
211 | mov ecx, socket_mutex |
212 | call mutex_unlock |
212 | call mutex_unlock |
213 | popa |
213 | popa |
214 | 214 | ||
215 | DEBUGF DEBUG_NETWORK_VERBOSE, "UDP_input: no socket found\n" |
215 | DEBUGF DEBUG_NETWORK_VERBOSE, "UDP_input: no socket found\n" |
216 | jmp .dump |
216 | jmp .dump |
217 | 217 | ||
218 | .checksum_mismatch: |
218 | .checksum_mismatch: |
219 | DEBUGF DEBUG_NETWORK_VERBOSE, "UDP_input: checksum mismatch\n" |
219 | DEBUGF DEBUG_NETWORK_VERBOSE, "UDP_input: checksum mismatch\n" |
220 | 220 | ||
221 | .dump: |
221 | .dump: |
222 | DEBUGF DEBUG_NETWORK_VERBOSE, "UDP_input: dumping\n" |
222 | DEBUGF DEBUG_NETWORK_VERBOSE, "UDP_input: dumping\n" |
223 | call net_buff_free |
223 | call net_buff_free |
224 | ret |
224 | ret |
225 | 225 | ||
226 | 226 | ||
227 | 227 | ||
228 | ;-----------------------------------------------------------------; |
228 | ;-----------------------------------------------------------------; |
229 | ; ; |
229 | ; ; |
230 | ; udp_output: Create an UDP packet. ; |
230 | ; udp_output: Create an UDP packet. ; |
231 | ; ; |
231 | ; ; |
232 | ; IN: eax = socket pointer ; |
232 | ; IN: eax = socket pointer ; |
233 | ; ecx = number of bytes to send ; |
233 | ; ecx = number of bytes to send ; |
234 | ; esi = pointer to data ; |
234 | ; esi = pointer to data ; |
235 | ; ; |
235 | ; ; |
236 | ; OUT: eax = -1 on error ; |
236 | ; OUT: eax = -1 on error ; |
237 | ; ; |
237 | ; ; |
238 | ;-----------------------------------------------------------------; |
238 | ;-----------------------------------------------------------------; |
239 | 239 | ||
240 | align 4 |
240 | align 4 |
241 | udp_output: |
241 | udp_output: |
242 | 242 | ||
243 | DEBUGF DEBUG_NETWORK_VERBOSE, "UDP_output: socket=%x bytes=%u data_ptr=%x\n", eax, ecx, esi |
243 | DEBUGF DEBUG_NETWORK_VERBOSE, "UDP_output: socket=%x bytes=%u data_ptr=%x\n", eax, ecx, esi |
244 | 244 | ||
245 | mov dx, [eax + UDP_SOCKET.RemotePort] |
245 | mov dx, [eax + UDP_SOCKET.RemotePort] |
246 | DEBUGF DEBUG_NETWORK_VERBOSE, "UDP_output: remote port=%x, ", dx ; FIXME: find a way to print big endian values with debugf |
246 | DEBUGF DEBUG_NETWORK_VERBOSE, "UDP_output: remote port=%x, ", dx ; FIXME: find a way to print big endian values with debugf |
247 | rol edx, 16 |
247 | rol edx, 16 |
248 | mov dx, [eax + UDP_SOCKET.LocalPort] |
248 | mov dx, [eax + UDP_SOCKET.LocalPort] |
249 | DEBUGF DEBUG_NETWORK_VERBOSE, "local port=%x\n", dx |
249 | DEBUGF DEBUG_NETWORK_VERBOSE, "local port=%x\n", dx |
250 | 250 | ||
251 | sub esp, 4 ; Data ptr will be placed here |
251 | sub esp, 4 ; Data ptr will be placed here |
252 | push edx esi |
252 | push edx esi |
253 | mov ebx, [eax + IP_SOCKET.device] |
253 | mov ebx, [eax + IP_SOCKET.device] |
254 | mov edx, [eax + IP_SOCKET.LocalIP] |
254 | mov edx, [eax + IP_SOCKET.LocalIP] |
255 | mov edi, [eax + IP_SOCKET.RemoteIP] |
255 | mov edi, [eax + IP_SOCKET.RemoteIP] |
256 | mov al, [eax + IP_SOCKET.ttl] |
256 | mov al, [eax + IP_SOCKET.ttl] |
257 | mov ah, IP_PROTO_UDP |
257 | mov ah, IP_PROTO_UDP |
258 | add ecx, sizeof.UDP_header |
258 | add ecx, sizeof.UDP_header |
259 | call ipv4_output |
259 | call ipv4_output |
260 | jz .fail |
260 | jz .fail |
261 | mov [esp + 8], eax ; pointer to buffer start |
261 | mov [esp + 8], eax ; pointer to buffer start |
262 | 262 | ||
263 | mov [edi + UDP_header.Length], cx |
263 | mov [edi + UDP_header.Length], cx |
264 | rol [edi + UDP_header.Length], 8 |
264 | rol [edi + UDP_header.Length], 8 |
265 | 265 | ||
266 | pop esi |
266 | pop esi |
267 | push edi ecx |
267 | push edi ecx |
268 | sub ecx, sizeof.UDP_header |
268 | sub ecx, sizeof.UDP_header |
269 | add edi, sizeof.UDP_header |
269 | add edi, sizeof.UDP_header |
270 | shr ecx, 2 |
270 | shr ecx, 2 |
271 | rep movsd |
271 | rep movsd |
272 | mov ecx, [esp] |
272 | mov ecx, [esp] |
273 | and ecx, 3 |
273 | and ecx, 3 |
274 | rep movsb |
274 | rep movsb |
275 | pop ecx edi |
275 | pop ecx edi |
276 | 276 | ||
277 | pop dword [edi + UDP_header.SourcePort] |
277 | pop dword [edi + UDP_header.SourcePort] |
278 | 278 | ||
279 | ; Checksum |
279 | ; Checksum |
280 | mov esi, edi |
280 | mov esi, edi |
281 | mov [edi + UDP_header.Checksum], 0 |
281 | mov [edi + UDP_header.Checksum], 0 |
282 | udp_checksum (edi-4), (edi-8) ; FIXME: IPv4 packet could have options.. |
282 | udp_checksum (edi-4), (edi-8) ; FIXME: IPv4 packet could have options.. |
283 | 283 | ||
284 | DEBUGF DEBUG_NETWORK_VERBOSE, "UDP_output: sending with device %x\n", ebx |
284 | DEBUGF DEBUG_NETWORK_VERBOSE, "UDP_output: sending with device %x\n", ebx |
285 | call [ebx + NET_DEVICE.transmit] |
285 | call [ebx + NET_DEVICE.transmit] |
286 | test eax, eax |
286 | test eax, eax |
287 | jnz @f |
287 | jnz @f |
288 | call net_ptr_to_num4 |
288 | call net_ptr_to_num4 |
289 | inc [UDP_packets_tx + edi] |
289 | inc [UDP_packets_tx + edi] |
290 | @@: |
290 | @@: |
291 | 291 | ||
292 | ret |
292 | ret |
293 | 293 | ||
294 | .fail: |
294 | .fail: |
295 | DEBUGF DEBUG_NETWORK_ERROR, "UDP_output: failed\n" |
295 | DEBUGF DEBUG_NETWORK_ERROR, "UDP_output: failed\n" |
296 | add esp, 4+4+8 |
296 | add esp, 4+4+8 |
297 | or eax, -1 |
297 | or eax, -1 |
298 | ret |
298 | ret |
299 | 299 | ||
300 | 300 | ||
301 | 301 | ||
302 | 302 | ||
303 | ;-----------------------------------------------------------------; |
303 | ;-----------------------------------------------------------------; |
304 | ; ; |
304 | ; ; |
305 | ; udp_connect ; |
305 | ; udp_connect ; |
306 | ; ; |
306 | ; ; |
307 | ; IN: eax = socket pointer ; |
307 | ; IN: eax = socket pointer ; |
- | 308 | ; edx = pointer to sockaddr struct ; |
|
308 | ; ; |
309 | ; ; |
309 | ; OUT: eax = 0 on success ; |
310 | ; OUT: eax = 0 on success ; |
310 | ; eax = -1 on error ; |
311 | ; eax = -1 on error ; |
311 | ; ebx = error code on error ; |
312 | ; ebx = error code on error ; |
312 | ; ; |
313 | ; ; |
313 | ;-----------------------------------------------------------------; |
314 | ;-----------------------------------------------------------------; |
314 | align 4 |
315 | align 4 |
315 | udp_connect: |
316 | udp_connect: |
316 | 317 | ||
317 | test [eax + SOCKET.state], SS_ISCONNECTED |
318 | test [eax + SOCKET.state], SS_ISCONNECTED |
318 | jz @f |
319 | jz @f |
319 | call udp_disconnect |
320 | call udp_disconnect |
320 | @@: |
321 | @@: |
321 | 322 | ||
322 | push eax edx |
323 | push eax edx |
323 | lea ecx, [eax + SOCKET.mutex] |
324 | lea ecx, [eax + SOCKET.mutex] |
324 | call mutex_lock |
325 | call mutex_lock |
325 | pop edx eax |
326 | pop edx eax |
326 | 327 | ||
327 | ; Fill in remote port and IP |
328 | ; Fill in remote port and IP |
328 | pushw [edx + 2] |
329 | pushw [edx + sockaddr.port] |
329 | pop [eax + UDP_SOCKET.RemotePort] |
330 | popw [eax + UDP_SOCKET.RemotePort] |
330 | 331 | ||
331 | pushd [edx + 4] |
332 | pushd [edx + sockaddr.ip] |
332 | pop [eax + UDP_SOCKET.RemoteIP] |
333 | pop [eax + UDP_SOCKET.RemoteIP] |
333 | 334 | ||
334 | ; Find route to host |
335 | ; Find route to host |
335 | pusha |
336 | pusha |
336 | push eax |
337 | push eax |
337 | mov ebx, [eax + UDP_SOCKET.device] |
338 | mov ebx, [eax + UDP_SOCKET.device] |
338 | mov edx, [eax + UDP_SOCKET.LocalIP] |
339 | mov edx, [eax + UDP_SOCKET.LocalIP] |
339 | mov eax, [eax + UDP_SOCKET.RemoteIP] |
340 | mov eax, [eax + UDP_SOCKET.RemoteIP] |
340 | call ipv4_route |
341 | call ipv4_route |
341 | test eax, eax |
342 | test eax, eax |
342 | jz .enoroute |
343 | jz .enoroute |
343 | pop eax |
344 | pop eax |
344 | mov ebx, [net_device_list + edi] |
345 | mov ebx, [net_device_list + edi] |
345 | mov [eax + UDP_SOCKET.device], ebx |
346 | mov [eax + UDP_SOCKET.device], ebx |
346 | mov [eax + UDP_SOCKET.LocalIP], edx |
347 | mov [eax + UDP_SOCKET.LocalIP], edx |
347 | popa |
348 | popa |
348 | 349 | ||
349 | ; Find a local port, if user didnt define one |
350 | ; Find a local port, if user didnt define one |
350 | cmp [eax + UDP_SOCKET.LocalPort], 0 |
351 | cmp [eax + UDP_SOCKET.LocalPort], 0 |
351 | jne @f |
352 | jne @f |
352 | call socket_find_port |
353 | call socket_find_port |
353 | @@: |
354 | @@: |
354 | 355 | ||
355 | push eax |
356 | push eax |
356 | lea ecx, [eax + SOCKET.mutex] |
357 | lea ecx, [eax + SOCKET.mutex] |
357 | call mutex_unlock |
358 | call mutex_unlock |
358 | pop eax |
359 | pop eax |
359 | 360 | ||
360 | call socket_is_connected |
361 | call socket_is_connected |
361 | 362 | ||
362 | xor eax, eax |
363 | xor eax, eax |
363 | ret |
364 | ret |
364 | 365 | ||
365 | .enoroute: |
366 | .enoroute: |
366 | pop eax |
367 | pop eax |
367 | 368 | ||
368 | push eax |
369 | push eax |
369 | lea ecx, [eax + SOCKET.mutex] |
370 | lea ecx, [eax + SOCKET.mutex] |
370 | call mutex_unlock |
371 | call mutex_unlock |
371 | pop eax |
372 | pop eax |
372 | 373 | ||
373 | popa |
374 | popa |
374 | xor eax, eax |
375 | xor eax, eax |
375 | dec eax |
376 | dec eax |
376 | mov ebx, EADDRNOTAVAIL |
377 | mov ebx, EADDRNOTAVAIL |
377 | ret |
378 | ret |
378 | 379 | ||
379 | 380 | ||
380 | ;-----------------------------------------------------------------; |
381 | ;-----------------------------------------------------------------; |
381 | ; ; |
382 | ; ; |
382 | ; UDP_disconnect ; |
383 | ; UDP_disconnect ; |
383 | ; ; |
384 | ; ; |
384 | ; IN: eax = socket pointer ; |
385 | ; IN: eax = socket pointer ; |
385 | ; ; |
386 | ; ; |
386 | ; OUT: eax = socket pointer ; |
387 | ; OUT: eax = socket pointer ; |
387 | ; ; |
388 | ; ; |
388 | ;-----------------------------------------------------------------; |
389 | ;-----------------------------------------------------------------; |
389 | align 4 |
390 | align 4 |
390 | udp_disconnect: |
391 | udp_disconnect: |
391 | 392 | ||
392 | ; TODO: remove the pending received data |
393 | ; TODO: remove the pending received data |
393 | 394 | ||
394 | call socket_is_disconnected |
395 | call socket_is_disconnected |
395 | 396 | ||
396 | ret |
397 | ret |
397 | 398 | ||
398 | 399 | ||
399 | 400 | ||
400 | 401 | ||
401 | 402 | ||
402 | ;-----------------------------------------------------------------; |
403 | ;-----------------------------------------------------------------; |
403 | ; ; |
404 | ; ; |
404 | ; UDP_api: Part of system function 76 ; |
405 | ; UDP_api: Part of system function 76 ; |
405 | ; ; |
406 | ; ; |
406 | ; IN: bl = subfunction number in bl ; |
407 | ; IN: bl = subfunction number in bl ; |
407 | ; bh = device number in bh ; |
408 | ; bh = device number in bh ; |
408 | ; ecx, edx, .. depends on subfunction ; |
409 | ; ecx, edx, .. depends on subfunction ; |
409 | ; ; |
410 | ; ; |
410 | ; OUT: depends on subfunction ; |
411 | ; OUT: depends on subfunction ; |
411 | ; ; |
412 | ; ; |
412 | ;-----------------------------------------------------------------; |
413 | ;-----------------------------------------------------------------; |
413 | align 4 |
414 | align 4 |
414 | udp_api: |
415 | udp_api: |
415 | 416 | ||
416 | movzx eax, bh |
417 | movzx eax, bh |
417 | shl eax, 2 |
418 | shl eax, 2 |
418 | 419 | ||
419 | test bl, bl |
420 | test bl, bl |
420 | jz .packets_tx ; 0 |
421 | jz .packets_tx ; 0 |
421 | dec bl |
422 | dec bl |
422 | jz .packets_rx ; 1 |
423 | jz .packets_rx ; 1 |
423 | 424 | ||
424 | .error: |
425 | .error: |
425 | mov eax, -1 |
426 | mov eax, -1 |
426 | ret |
427 | ret |
427 | 428 | ||
428 | .packets_tx: |
429 | .packets_tx: |
429 | mov eax, [UDP_packets_tx + eax] |
430 | mov eax, [UDP_packets_tx + eax] |
430 | ret |
431 | ret |
431 | 432 | ||
432 | .packets_rx: |
433 | .packets_rx: |
433 | mov eax, [UDP_packets_rx + eax] |
434 | mov eax, [UDP_packets_rx + eax] |
434 | ret |
435 | ret |