Rev 2465 | Rev 3589 | Go to most recent revision | Show entire file | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 2465 | Rev 3555 | ||
---|---|---|---|
Line 1... | Line 1... | ||
1 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
1 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
2 | ;; ;; |
2 | ;; ;; |
3 | ;; Copyright (C) KolibriOS team 2004-2011. All rights reserved. ;; |
3 | ;; Copyright (C) KolibriOS team 2004-2013. 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 | ;; SOCKET.INC ;; |
6 | ;; Part of the TCP/IP network stack for KolibriOS ;; |
7 | ;; ;; |
7 | ;; ;; |
8 | ;; Sockets constants, structures and functions ;; |
8 | ;; Written by hidnplayr@kolibrios.org, ;; |
- | 9 | ;; and Clevermouse. ;; |
|
9 | ;; ;; |
10 | ;; ;; |
10 | ;; This file contains the following: ;; |
- | |
11 | ;; is_localport_unused ;; |
- | |
12 | ;; get_free_socket ;; |
- | |
13 | ;; socket_open ;; |
11 | ;; Based on code by mike.dld ;; |
14 | ;; socket_open_tcp ;; |
- | |
15 | ;; socket_close ;; |
- | |
16 | ;; socket_close_tcp ;; |
- | |
17 | ;; socket_poll ;; |
- | |
18 | ;; socket_status ;; |
- | |
19 | ;; socket_read ;; |
- | |
20 | ;; socket_write ;; |
- | |
21 | ;; socket_write_tcp ;; |
- | |
22 | ;; ;; |
12 | ;; ;; |
- | 13 | ;; GNU GENERAL PUBLIC LICENSE ;; |
|
- | 14 | ;; Version 2, June 1991 ;; |
|
23 | ;; ;; |
15 | ;; ;; |
24 | ;; Changes history: ;; |
- | |
25 | ;; 22.09.2003 - [Mike Hibbett] : mikeh@oceanfree.net ;; |
- | |
26 | ;; 11.11.2006 - [Johnny_B] and [smb] ;; |
- | |
27 | ;; ;; |
- | |
28 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
16 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
- | 17 | ||
- | 18 | $Revision: 3555 $ |
|
Line 29... | Line -... | ||
29 | - | ||
Line 30... | Line -... | ||
30 | $Revision: 2465 $ |
- | |
31 | 19 | ||
32 | ; socket data structure |
- | |
- | 20 | ||
33 | struct SOCKET |
21 | struct SOCKET |
34 | PrevPtr dd ? ; pointer to previous socket in list |
22 | |
- | 23 | NextPtr dd ? ; pointer to next socket in list |
|
- | 24 | PrevPtr dd ? ; pointer to previous socket in list |
|
- | 25 | Number dd ? ; socket number |
|
- | 26 | ||
35 | NextPtr dd ? ; pointer to next socket in list |
27 | mutex MUTEX |
36 | Number dd ? ; socket number (unique within single process) |
28 | |
37 | PID dd ? ; application process id |
29 | PID dd ? ; process ID |
38 | LocalIP dd ? ; local IP address |
30 | TID dd ? ; thread ID |
- | 31 | Domain dd ? ; INET/LOCAL/.. |
|
39 | LocalPort dw ? ; local port |
32 | Type dd ? ; RAW/STREAM/DGRAP |
40 | RemoteIP dd ? ; remote IP address |
33 | Protocol dd ? ; ICMP/IPv4/ARP/TCP/UDP |
- | 34 | errorcode dd ? |
|
- | 35 | device dd ? ; driver pointer, socket pointer if it's an LOCAL socket |
|
- | 36 | ||
41 | RemotePort dw ? ; remote port |
37 | options dd ? |
- | 38 | state dd ? |
|
42 | OrigRemoteIP dd ? ; original remote IP address (used to reset to LISTEN state) |
39 | backlog dw ? ; how many incoming connections that can be queued |
43 | OrigRemotePort dw ? ; original remote port (used to reset to LISTEN state) |
40 | |
- | 41 | snd_proc dd ? |
|
- | 42 | rcv_proc dd ? |
|
- | 43 | ||
- | 44 | ends |
|
- | 45 | ||
- | 46 | struct IP_SOCKET SOCKET |
|
- | 47 | ||
- | 48 | LocalIP rd 4 ; network byte order |
|
- | 49 | RemoteIP rd 4 ; network byte order |
|
- | 50 | ||
- | 51 | ends |
|
- | 52 | ||
44 | rxDataCount dd ? ; rx data count |
53 | struct TCP_SOCKET IP_SOCKET |
45 | TCBState dd ? ; TCB state |
54 | |
- | 55 | LocalPort dw ? ; network byte order |
|
- | 56 | RemotePort dw ? ; network byte order |
|
- | 57 | ||
46 | TCBTimer dd ? ; TCB timer (seconds) |
58 | t_state dd ? ; TCB state |
- | 59 | t_rxtshift db ? |
|
- | 60 | rb 3 ; align |
|
- | 61 | t_rxtcur dd ? |
|
- | 62 | t_dupacks dd ? |
|
- | 63 | t_maxseg dd ? |
|
- | 64 | t_force dd ? |
|
- | 65 | t_flags dd ? |
|
- | 66 | ||
- | 67 | ;--------------- |
|
- | 68 | ; RFC783 page 21 |
|
47 | ISS dd ? ; initial send sequence |
69 | |
48 | IRS dd ? ; initial receive sequence |
70 | ; send sequence |
- | 71 | SND_UNA dd ? ; sequence number of unack'ed sent Packets |
|
- | 72 | SND_NXT dd ? ; next send sequence number to use |
|
- | 73 | SND_UP dd ? ; urgent pointer |
|
- | 74 | SND_WL1 dd ? ; window minus one |
|
49 | SND_UNA dd ? ; sequence number of unack'ed sent packets |
75 | SND_WL2 dd ? ; |
- | 76 | ISS dd ? ; initial send sequence number |
|
50 | SND_NXT dd ? ; bext send sequence number to use |
77 | SND_WND dd ? ; send window |
51 | SND_WND dd ? ; send window |
78 | |
- | 79 | ; receive sequence |
|
52 | RCV_NXT dd ? ; next receive sequence number to use |
80 | RCV_WND dd ? ; receive window |
- | 81 | RCV_NXT dd ? ; next receive sequence number to use |
|
- | 82 | RCV_UP dd ? ; urgent pointer |
|
- | 83 | IRS dd ? ; initial receive sequence number |
|
- | 84 | ||
- | 85 | ;--------------------- |
|
- | 86 | ; Additional variables |
|
- | 87 | ||
- | 88 | ; receive variables |
|
- | 89 | RCV_ADV dd ? |
|
- | 90 | ||
- | 91 | ; retransmit variables |
|
- | 92 | SND_MAX dd ? |
|
53 | RCV_WND dd ? ; receive window |
93 | |
- | 94 | ; congestion control |
|
- | 95 | SND_CWND dd ? |
|
- | 96 | SND_SSTHRESH dd ? |
|
- | 97 | ||
- | 98 | ;---------------------- |
|
- | 99 | ; Transmit timing stuff |
|
- | 100 | t_idle dd ? |
|
- | 101 | t_rtt dd ? |
|
- | 102 | t_rtseq dd ? |
|
- | 103 | t_srtt dd ? |
|
- | 104 | t_rttvar dd ? |
|
- | 105 | t_rttmin dd ? |
|
- | 106 | max_sndwnd dd ? |
|
- | 107 | ||
- | 108 | ;----------------- |
|
- | 109 | ; Out-of-band data |
|
- | 110 | t_oobflags dd ? |
|
- | 111 | t_iobc dd ? |
|
- | 112 | t_softerror dd ? |
|
- | 113 | ||
- | 114 | ||
- | 115 | ;--------- |
|
- | 116 | ; RFC 1323 ; the order of next 4 elements may not change |
|
- | 117 | ||
- | 118 | SND_SCALE db ? |
|
- | 119 | RCV_SCALE db ? |
|
- | 120 | requested_s_scale db ? |
|
- | 121 | request_r_scale db ? |
|
- | 122 | ||
- | 123 | ts_recent dd ? ; a copy of the most-recent valid timestamp from the other end |
|
- | 124 | ts_recent_age dd ? |
|
- | 125 | last_ack_sent dd ? |
|
- | 126 | ||
- | 127 | ||
- | 128 | ;------- |
|
- | 129 | ; Timers |
|
- | 130 | timer_retransmission dd ? ; rexmt |
|
54 | SEG_LEN dd ? ; segment length |
131 | timer_persist dd ? |
- | 132 | timer_keepalive dd ? ; keepalive/syn timeout |
|
- | 133 | timer_timed_wait dd ? ; also used as 2msl timer |
|
- | 134 | ||
- | 135 | ; extra |
|
- | 136 | ||
- | 137 | ts_ecr dd ? ; timestamp echo reply |
|
- | 138 | ts_val dd ? |
|
- | 139 | ||
- | 140 | seg_next dd ? ; re-assembly queue |
|
- | 141 | ||
- | 142 | temp_bits db ? |
|
- | 143 | rb 3 ; align |
|
- | 144 | ||
- | 145 | ends |
|
- | 146 | ||
- | 147 | struct UDP_SOCKET IP_SOCKET |
|
- | 148 | ||
- | 149 | LocalPort dw ? ; network byte order |
|
- | 150 | RemotePort dw ? ; network byte order |
|
- | 151 | firstpacket db ? |
|
- | 152 | ||
- | 153 | ends |
|
- | 154 | ||
- | 155 | ||
- | 156 | struct ICMP_SOCKET IP_SOCKET |
|
- | 157 | ||
- | 158 | Identifier dw ? |
|
- | 159 | ||
- | 160 | ends |
|
- | 161 | ||
- | 162 | ||
55 | SEG_WND dd ? ; segment window |
163 | struct RING_BUFFER |
- | 164 | ||
- | 165 | mutex MUTEX |
|
- | 166 | start_ptr dd ? ; Pointer to start of buffer |
|
- | 167 | end_ptr dd ? ; pointer to end of buffer |
|
56 | wndsizeTimer dd ? ; window size timer |
168 | read_ptr dd ? ; Read pointer |
- | 169 | write_ptr dd ? ; Write pointer |
|
- | 170 | size dd ? ; Number of bytes buffered |
|
- | 171 | ||
- | 172 | ends |
|
- | 173 | ||
- | 174 | struct STREAM_SOCKET TCP_SOCKET |
|
- | 175 | ||
- | 176 | rcv RING_BUFFER |
|
- | 177 | snd RING_BUFFER |
|
- | 178 | ||
- | 179 | ends |
|
- | 180 | ||
- | 181 | struct socket_queue_entry |
|
- | 182 | ||
- | 183 | data_ptr dd ? |
|
- | 184 | buf_ptr dd ? |
|
57 | mutex MUTEX ; lock mutex |
185 | data_size dd ? |
Line 58... | Line -... | ||
58 | rxData dd ? ; receive data buffer here |
- | |
59 | ends |
- | |
60 | - | ||
61 | ; TCP opening modes |
- | |
62 | SOCKET_PASSIVE = 0 |
- | |
63 | SOCKET_ACTIVE = 1 |
- | |
64 | - | ||
Line 65... | Line 186... | ||
65 | ; socket types |
186 | |
- | 187 | ends |
|
- | 188 | ||
- | 189 | ||
- | 190 | SOCKETBUFFSIZE = 4096 ; in bytes |
|
- | 191 | ||
66 | SOCK_STREAM = 1 |
192 | SOCKET_QUEUE_SIZE = 10 ; maximum number of incoming packets queued for 1 socket |
- | 193 | ; the incoming packet queue for sockets is placed in the socket struct itself, at this location from start |
|
67 | SOCK_DGRAM = 2 |
194 | SOCKET_QUEUE_LOCATION = (SOCKETBUFFSIZE - SOCKET_QUEUE_SIZE*sizeof.socket_queue_entry - sizeof.queue) |
- | 195 | ||
68 | 196 | uglobal |
|
69 | ; pointer to bitmap of free ports (1=free, 0=used) |
197 | net_sockets rd 4 |
Line 70... | Line -... | ||
70 | uglobal |
- | |
71 | align 4 |
- | |
72 | network_free_ports dd ? |
- | |
73 | endg |
- | |
Line 74... | Line 198... | ||
74 | 198 | last_socket_num dd ? |
|
75 | iglobal |
- | |
76 | align 4 |
- | |
77 | network_free_hint dd 1024/8 |
199 | last_UDP_port dw ? ; These values give the number of the last used ephemeral port |
78 | endg |
200 | last_TCP_port dw ? ; |
79 | 201 | endg |
|
80 | ;; Allocate memory for socket data and put new socket into the list |
- | |
81 | ; Newly created socket is initialized with calling PID and number and |
- | |
82 | ; put into beginning of list (which is a fastest way). |
- | |
83 | ; |
202 | |
84 | ; @return socket structure address in EAX |
- | |
85 | ;; |
203 | |
Line 86... | Line -... | ||
86 | proc net_socket_alloc stdcall uses ebx ecx edx edi |
- | |
87 | stdcall kernel_alloc, SOCKETBUFFSIZE |
- | |
88 | DEBUGF 1, "K : net_socket_alloc (0x%x)\n", eax |
- | |
89 | ; check if we can allocate needed amount of memory |
- | |
90 | or eax, eax |
- | |
91 | jz .exit |
204 | ;----------------------------------------------------------------- |
- | 205 | ; |
|
- | 206 | ; SOCKET_init |
|
92 | 207 | ; |
|
- | 208 | ;----------------------------------------------------------------- |
|
- | 209 | macro SOCKET_init { |
|
- | 210 | ||
- | 211 | xor eax, eax |
|
- | 212 | mov edi, net_sockets |
|
- | 213 | mov ecx, 5 |
|
- | 214 | rep stosd |
|
- | 215 | ||
- | 216 | @@: |
|
- | 217 | pseudo_random eax |
|
- | 218 | cmp ax, MIN_EPHEMERAL_PORT |
|
- | 219 | jb @r |
|
- | 220 | cmp ax, MAX_EPHEMERAL_PORT |
|
- | 221 | ja @r |
|
- | 222 | xchg al, ah |
|
- | 223 | mov [last_UDP_port], ax |
|
- | 224 | ||
- | 225 | @@: |
|
- | 226 | pseudo_random eax |
|
- | 227 | cmp ax, MIN_EPHEMERAL_PORT |
|
- | 228 | jb @r |
|
- | 229 | cmp ax, MAX_EPHEMERAL_PORT |
|
- | 230 | ja @r |
|
- | 231 | xchg al, ah |
|
- | 232 | mov [last_TCP_port], ax |
|
- | 233 | ||
- | 234 | } |
|
- | 235 | ||
- | 236 | ;----------------------------------------------------------------- |
|
- | 237 | ; |
|
- | 238 | ; Socket API (function 74) |
|
- | 239 | ; |
|
- | 240 | ;----------------------------------------------------------------- |
|
- | 241 | align 4 |
|
- | 242 | sys_socket: |
|
- | 243 | ||
- | 244 | cmp ebx, 255 |
|
- | 245 | jz SOCKET_debug |
|
- | 246 | ||
- | 247 | cmp ebx, .number |
|
- | 248 | ja s_error |
|
- | 249 | jmp dword [.table + 4*ebx] |
|
- | 250 | ||
- | 251 | .table: |
|
- | 252 | dd SOCKET_open ; 0 |
|
- | 253 | dd SOCKET_close ; 1 |
|
- | 254 | dd SOCKET_bind ; 2 |
|
- | 255 | dd SOCKET_listen ; 3 |
|
- | 256 | dd SOCKET_connect ; 4 |
|
- | 257 | dd SOCKET_accept ; 5 |
|
- | 258 | dd SOCKET_send ; 6 |
|
- | 259 | dd SOCKET_receive ; 7 |
|
- | 260 | dd SOCKET_set_opt ; 8 |
|
- | 261 | dd SOCKET_get_opt ; 9 |
|
- | 262 | dd SOCKET_pair ; 10 |
|
- | 263 | .number = ($ - .table) / 4 - 1 |
|
- | 264 | ||
- | 265 | s_error: |
|
- | 266 | DEBUGF 2,"SOCKET: error\n" |
|
- | 267 | mov dword [esp+32], -1 |
|
- | 268 | ||
- | 269 | ret |
|
- | 270 | ||
- | 271 | ;----------------------------------------------------------------- |
|
- | 272 | ; |
|
- | 273 | ; SOCKET_open |
|
- | 274 | ; |
|
- | 275 | ; IN: domain in ecx |
|
- | 276 | ; type in edx |
|
- | 277 | ; protocol in esi |
|
- | 278 | ; OUT: eax is socket num, -1 on error |
|
- | 279 | ; |
|
- | 280 | ;----------------------------------------------------------------- |
|
- | 281 | align 4 |
|
- | 282 | SOCKET_open: |
|
- | 283 | ||
- | 284 | DEBUGF 2,"SOCKET_open: domain=%u type=%u protocol=%x ", ecx, edx, esi |
|
- | 285 | ||
- | 286 | push ecx edx esi |
|
- | 287 | call SOCKET_alloc |
|
- | 288 | pop esi edx ecx |
|
- | 289 | jz s_error |
|
- | 290 | ||
- | 291 | mov [esp+32], edi ; return socketnumber |
|
- | 292 | DEBUGF 2,"socknum=%u\n", edi |
|
- | 293 | ||
- | 294 | ; push edx |
|
- | 295 | ; and edx, SO_NONBLOCK |
|
- | 296 | or [eax + SOCKET.options], SO_NONBLOCK ;edx |
|
- | 297 | ; pop edx |
|
- | 298 | ; and edx, not SO_NONBLOCK |
|
- | 299 | ||
- | 300 | mov [eax + SOCKET.Domain], ecx |
|
- | 301 | mov [eax + SOCKET.Type], edx |
|
- | 302 | mov [eax + SOCKET.Protocol], esi |
|
- | 303 | ||
- | 304 | cmp ecx, AF_INET4 |
|
- | 305 | jne .no_inet4 |
|
- | 306 | ||
- | 307 | cmp edx, SOCK_DGRAM |
|
- | 308 | je .udp |
|
- | 309 | ||
- | 310 | cmp edx, SOCK_STREAM |
|
- | 311 | je .tcp |
|
- | 312 | ||
- | 313 | cmp edx, SOCK_RAW |
|
- | 314 | je .raw |
|
- | 315 | ||
- | 316 | .no_inet4: |
|
- | 317 | cmp ecx, AF_PPP |
|
- | 318 | jne .no_ppp |
|
- | 319 | ||
- | 320 | cmp esi, PPP_PROTO_ETHERNET |
|
- | 321 | je .pppoe |
|
- | 322 | ||
- | 323 | .no_ppp: |
|
- | 324 | DEBUGF 2,"Unknown socket family/protocol\n" |
|
- | 325 | ret |
|
- | 326 | ||
- | 327 | align 4 |
|
- | 328 | .raw: |
|
- | 329 | test esi, esi ; IP_PROTO_IP |
|
- | 330 | jz .ip |
|
- | 331 | ||
- | 332 | cmp esi, IP_PROTO_ICMP |
|
- | 333 | je .icmp |
|
- | 334 | ||
- | 335 | cmp esi, IP_PROTO_UDP |
|
- | 336 | je .udp |
|
- | 337 | ||
- | 338 | cmp esi, IP_PROTO_TCP |
|
- | 339 | je .tcp |
|
- | 340 | ||
- | 341 | ret |
|
- | 342 | ||
- | 343 | align 4 |
|
- | 344 | .udp: |
|
- | 345 | mov [eax + SOCKET.Protocol], IP_PROTO_UDP |
|
- | 346 | mov [eax + SOCKET.snd_proc], SOCKET_send_udp |
|
- | 347 | mov [eax + SOCKET.rcv_proc], SOCKET_receive_dgram |
|
- | 348 | ret |
|
- | 349 | ||
- | 350 | align 4 |
|
- | 351 | .tcp: |
|
- | 352 | mov [eax + SOCKET.Protocol], IP_PROTO_TCP |
|
- | 353 | mov [eax + SOCKET.snd_proc], SOCKET_send_tcp |
|
- | 354 | mov [eax + SOCKET.rcv_proc], SOCKET_receive_stream |
|
- | 355 | ||
- | 356 | TCP_init_socket eax |
|
- | 357 | ret |
|
- | 358 | ||
- | 359 | ||
- | 360 | align 4 |
|
- | 361 | .ip: |
|
- | 362 | mov [eax + SOCKET.snd_proc], SOCKET_send_ip |
|
- | 363 | mov [eax + SOCKET.rcv_proc], SOCKET_receive_dgram |
|
- | 364 | ret |
|
- | 365 | ||
- | 366 | ||
- | 367 | align 4 |
|
- | 368 | .icmp: |
|
- | 369 | mov [eax + SOCKET.snd_proc], SOCKET_send_icmp |
|
93 | ; zero-initialize allocated memory |
370 | mov [eax + SOCKET.rcv_proc], SOCKET_receive_dgram |
Line -... | Line 371... | ||
- | 371 | ret |
|
- | 372 | ||
- | 373 | align 4 |
|
- | 374 | .pppoe: |
|
- | 375 | push eax |
|
- | 376 | init_queue (eax + SOCKET_QUEUE_LOCATION) ; Set up data receiving queue |
|
- | 377 | pop eax |
|
- | 378 | ||
- | 379 | mov [eax + SOCKET.snd_proc], SOCKET_send_pppoe |
|
- | 380 | mov [eax + SOCKET.rcv_proc], SOCKET_receive_dgram |
|
- | 381 | ret |
|
- | 382 | ||
- | 383 | ||
- | 384 | ;----------------------------------------------------------------- |
|
- | 385 | ; |
|
- | 386 | ; SOCKET_bind |
|
- | 387 | ; |
|
- | 388 | ; IN: socket number in ecx |
|
- | 389 | ; pointer to sockaddr struct in edx |
|
- | 390 | ; length of that struct in esi |
|
- | 391 | ; OUT: 0 on success |
|
- | 392 | ; |
|
- | 393 | ;----------------------------------------------------------------- |
|
- | 394 | align 4 |
|
- | 395 | SOCKET_bind: |
|
- | 396 | ||
- | 397 | DEBUGF 2,"SOCKET_bind: socknum=%u sockaddr=%x length=%u\n", ecx, edx, esi |
|
- | 398 | ||
- | 399 | call SOCKET_num_to_ptr |
|
- | 400 | jz s_error |
|
- | 401 | ||
- | 402 | cmp esi, 2 |
|
- | 403 | jb s_error |
|
- | 404 | ||
- | 405 | cmp word [edx], AF_INET4 |
|
- | 406 | je .af_inet4 |
|
- | 407 | ||
- | 408 | cmp word [edx], AF_LOCAL |
|
- | 409 | je .af_local |
|
- | 410 | ||
- | 411 | jmp s_error |
|
- | 412 | ||
- | 413 | .af_local: |
|
- | 414 | ; TODO: write code here |
|
- | 415 | ||
- | 416 | mov dword [esp+32], 0 |
|
- | 417 | ret |
|
- | 418 | ||
- | 419 | .af_inet4: |
|
- | 420 | ||
- | 421 | cmp esi, 6 |
|
- | 422 | jb s_error |
|
- | 423 | ||
- | 424 | cmp [eax + SOCKET.Protocol], IP_PROTO_UDP |
|
- | 425 | je .udp |
|
- | 426 | ||
- | 427 | cmp [eax + SOCKET.Protocol], IP_PROTO_TCP |
|
- | 428 | je .tcp |
|
- | 429 | ||
- | 430 | jmp s_error |
|
- | 431 | ||
- | 432 | .tcp: |
|
- | 433 | .udp: |
|
- | 434 | ||
- | 435 | mov ebx, [edx + 4] ; First, fill in the IP |
|
- | 436 | test ebx, ebx ; If IP is 0, use default |
|
- | 437 | jnz @f |
|
- | 438 | mov ebx, [NET_DEFAULT] |
|
- | 439 | mov ebx, [IP_LIST + 4*ebx] |
|
- | 440 | @@: |
|
- | 441 | mov [eax + IP_SOCKET.LocalIP], ebx |
|
- | 442 | ||
- | 443 | mov bx, [edx + 2] ; Now fill in the local port if it's still available |
|
- | 444 | call SOCKET_check_port |
|
- | 445 | jz s_error ; ZF is set by socket_check_port, on error |
|
- | 446 | ||
- | 447 | DEBUGF 1,"SOCKET_bind: local ip=%u.%u.%u.%u\n",\ |
|
- | 448 | [eax + IP_SOCKET.LocalIP + 0]:1,[eax + IP_SOCKET.LocalIP + 1]:1,\ |
|
- | 449 | [eax + IP_SOCKET.LocalIP + 2]:1,[eax + IP_SOCKET.LocalIP + 3]:1 |
|
- | 450 | ||
- | 451 | mov dword [esp+32], 0 |
|
- | 452 | ret |
|
- | 453 | ||
- | 454 | ||
- | 455 | ||
- | 456 | ||
- | 457 | ;----------------------------------------------------------------- |
|
- | 458 | ; |
|
- | 459 | ; SOCKET_connect |
|
- | 460 | ; |
|
- | 461 | ; IN: socket number in ecx |
|
- | 462 | ; pointer to sockaddr struct in edx |
|
- | 463 | ; length of that struct in esi |
|
- | 464 | ; OUT: 0 on success |
|
- | 465 | ; |
|
- | 466 | ;----------------------------------------------------------------- |
|
94 | push eax |
467 | align 4 |
- | 468 | SOCKET_connect: |
|
- | 469 | ||
- | 470 | DEBUGF 2,"SOCKET_connect: socknum=%u sockaddr=%x length=%u\n", ecx, edx, esi |
|
- | 471 | ||
- | 472 | call SOCKET_num_to_ptr |
|
- | 473 | jz s_error |
|
- | 474 | ||
- | 475 | cmp esi, 8 |
|
- | 476 | jb s_error |
|
- | 477 | ||
- | 478 | cmp word [edx], AF_INET4 |
|
- | 479 | je .af_inet4 |
|
- | 480 | ||
- | 481 | jmp s_error |
|
- | 482 | ||
- | 483 | .af_inet4: |
|
- | 484 | cmp [eax + IP_SOCKET.LocalIP], 0 |
|
- | 485 | jne @f |
|
- | 486 | push [IP_LIST] ; FIXME |
|
- | 487 | pop [eax + IP_SOCKET.LocalIP] |
|
- | 488 | @@: |
|
- | 489 | ||
- | 490 | cmp [eax + SOCKET.Protocol], IP_PROTO_UDP |
|
- | 491 | je .udp |
|
- | 492 | ||
- | 493 | cmp [eax + SOCKET.Protocol], IP_PROTO_TCP |
|
- | 494 | je .tcp |
|
- | 495 | ||
- | 496 | cmp [eax + SOCKET.Protocol], IP_PROTO_IP |
|
- | 497 | je .ip |
|
- | 498 | ||
95 | mov edi, eax |
499 | cmp [eax + SOCKET.Protocol], IP_PROTO_ICMP |
96 | mov ecx, SOCKETBUFFSIZE / 4 |
500 | je .ip |
- | 501 | ||
- | 502 | jmp s_error |
|
- | 503 | ||
- | 504 | align 4 |
|
- | 505 | .udp: |
|
- | 506 | pusha |
|
- | 507 | lea ecx, [eax + SOCKET.mutex] |
|
- | 508 | call mutex_lock |
|
- | 509 | popa |
|
- | 510 | ||
- | 511 | pushw [edx + 2] |
|
- | 512 | pop [eax + UDP_SOCKET.RemotePort] |
|
- | 513 | ||
- | 514 | pushd [edx + 4] |
|
- | 515 | pop [eax + IP_SOCKET.RemoteIP] |
|
- | 516 | ||
- | 517 | cmp [eax + UDP_SOCKET.LocalPort], 0 |
|
- | 518 | jne @f |
|
- | 519 | call SOCKET_find_port |
|
- | 520 | @@: |
|
- | 521 | ||
- | 522 | mov [eax + UDP_SOCKET.firstpacket], 0 |
|
- | 523 | ||
- | 524 | push eax |
|
- | 525 | init_queue (eax + SOCKET_QUEUE_LOCATION) ; Set up data receiving queue |
|
- | 526 | pop eax |
|
- | 527 | ||
- | 528 | lea ecx, [eax + SOCKET.mutex] |
|
- | 529 | call mutex_unlock |
|
- | 530 | ||
- | 531 | mov dword [esp+32], 0 |
|
- | 532 | ret |
|
- | 533 | ||
- | 534 | align 4 |
|
- | 535 | .tcp: |
|
- | 536 | pusha |
|
- | 537 | lea ecx, [eax + SOCKET.mutex] |
|
- | 538 | call mutex_lock |
|
- | 539 | popa |
|
- | 540 | ||
- | 541 | pushw [edx + 2] |
|
- | 542 | pop [eax + TCP_SOCKET.RemotePort] |
|
- | 543 | ||
- | 544 | pushd [edx + 4] |
|
- | 545 | pop [eax + IP_SOCKET.RemoteIP] |
|
- | 546 | ||
- | 547 | cmp [eax + TCP_SOCKET.LocalPort], 0 |
|
- | 548 | jne @f |
|
- | 549 | call SOCKET_find_port |
|
- | 550 | @@: |
|
- | 551 | ||
- | 552 | mov [eax + TCP_SOCKET.timer_persist], 0 |
|
- | 553 | mov [eax + TCP_SOCKET.t_state], TCPS_SYN_SENT |
|
- | 554 | ||
- | 555 | push [TCP_sequence_num] |
|
- | 556 | add [TCP_sequence_num], 6400 |
|
- | 557 | pop [eax + TCP_SOCKET.ISS] |
|
- | 558 | mov [eax + TCP_SOCKET.timer_keepalive], TCP_time_keep_init |
|
- | 559 | ||
- | 560 | ||
- | 561 | TCP_sendseqinit eax |
|
- | 562 | ||
- | 563 | ; mov [ebx + TCP_SOCKET.timer_retransmission], ;; todo: create macro to set retransmission timer |
|
- | 564 | ||
- | 565 | mov ebx, eax |
|
- | 566 | ||
- | 567 | lea eax, [ebx + STREAM_SOCKET.snd] |
|
- | 568 | call SOCKET_ring_create |
|
- | 569 | ||
97 | cld |
570 | lea eax, [ebx + STREAM_SOCKET.rcv] |
- | 571 | call SOCKET_ring_create |
|
Line 98... | Line 572... | ||
98 | xor eax, eax |
572 | |
- | 573 | pusha |
|
99 | rep stosd |
574 | lea ecx, [ebx + SOCKET.mutex] |
- | 575 | call mutex_unlock |
|
- | 576 | popa |
|
- | 577 | ||
- | 578 | mov eax, ebx |
|
- | 579 | call TCP_output |
|
- | 580 | ||
- | 581 | ;;; TODO: wait for successfull connection if blocking socket |
|
- | 582 | ||
- | 583 | mov dword [esp+32], 0 |
|
- | 584 | ret |
|
100 | pop eax |
585 | |
- | 586 | align 4 |
|
- | 587 | .ip: |
|
- | 588 | pusha |
|
- | 589 | lea ecx, [eax + SOCKET.mutex] |
|
- | 590 | call mutex_lock |
|
- | 591 | popa |
|
- | 592 | ||
- | 593 | pushd [edx + 4] |
|
- | 594 | pop [eax + IP_SOCKET.RemoteIP] |
|
- | 595 | ||
- | 596 | push eax |
|
- | 597 | init_queue (eax + SOCKET_QUEUE_LOCATION) ; Set up data receiving queue |
|
- | 598 | pop eax |
|
- | 599 | ||
- | 600 | lea ecx, [eax + SOCKET.mutex] |
|
- | 601 | call mutex_unlock |
|
- | 602 | ||
- | 603 | mov dword [esp+32], 0 |
|
- | 604 | ret |
|
- | 605 | ||
- | 606 | ||
- | 607 | ;----------------------------------------------------------------- |
|
- | 608 | ; |
|
- | 609 | ; SOCKET_listen |
|
- | 610 | ; |
|
- | 611 | ; IN: socket number in ecx |
|
- | 612 | ; backlog in edx |
|
- | 613 | ; OUT: eax is socket num, -1 on error |
|
- | 614 | ; |
|
- | 615 | ;----------------------------------------------------------------- |
|
- | 616 | align 4 |
|
- | 617 | SOCKET_listen: |
|
- | 618 | ||
- | 619 | DEBUGF 2,"SOCKET_listen: socknum=%u backlog=%u\n", ecx, edx |
|
- | 620 | ||
- | 621 | call SOCKET_num_to_ptr |
|
- | 622 | jz s_error |
|
- | 623 | ||
101 | 624 | cmp [eax + SOCKET.Domain], AF_INET4 |
|
- | 625 | jne s_error |
|
- | 626 | ||
- | 627 | cmp [eax + SOCKET.Protocol], IP_PROTO_TCP |
|
- | 628 | jne s_error |
|
- | 629 | ||
- | 630 | cmp [eax + TCP_SOCKET.LocalPort], 0 |
|
- | 631 | je s_error |
|
- | 632 | ||
- | 633 | cmp [eax + IP_SOCKET.LocalIP], 0 |
|
- | 634 | jne @f |
|
102 | mov ebx, eax |
635 | push [IP_LIST] |
- | 636 | pop [eax + IP_SOCKET.LocalIP] |
|
- | 637 | @@: |
|
- | 638 | ||
- | 639 | cmp edx, MAX_backlog |
|
- | 640 | jbe @f |
|
- | 641 | mov edx, MAX_backlog |
|
103 | lea ecx, [eax+SOCKET.mutex] |
642 | @@: |
- | 643 | ||
- | 644 | mov [eax + SOCKET.backlog], dx |
|
- | 645 | or [eax + SOCKET.options], SO_ACCEPTCON |
|
- | 646 | mov [eax + TCP_SOCKET.t_state], TCPS_LISTEN |
|
- | 647 | mov [eax + TCP_SOCKET.timer_keepalive], 0 ; disable keepalive timer |
|
- | 648 | ||
- | 649 | push eax |
|
- | 650 | init_queue (eax + SOCKET_QUEUE_LOCATION) ; Set up sockets queue |
|
- | 651 | pop eax |
|
- | 652 | ||
- | 653 | mov dword [esp+32], 0 |
|
- | 654 | ||
- | 655 | ret |
|
- | 656 | ||
- | 657 | ||
- | 658 | ;----------------------------------------------------------------- |
|
- | 659 | ; |
|
- | 660 | ; SOCKET_accept |
|
- | 661 | ; |
|
- | 662 | ; IN: socket number in ecx |
|
- | 663 | ; addr in edx |
|
- | 664 | ; addrlen in esi |
|
- | 665 | ; OUT: eax is socket num, -1 on error |
|
- | 666 | ; |
|
- | 667 | ;----------------------------------------------------------------- |
|
- | 668 | align 4 |
|
- | 669 | SOCKET_accept: |
|
- | 670 | ||
- | 671 | DEBUGF 2,"SOCKET_accept: socknum=%u sockaddr=%x length=%u\n", ecx, edx, esi |
|
- | 672 | ||
- | 673 | call SOCKET_num_to_ptr |
|
- | 674 | jz s_error |
|
- | 675 | ||
- | 676 | test [eax + SOCKET.options], SO_ACCEPTCON |
|
- | 677 | jz s_error |
|
- | 678 | ||
- | 679 | cmp [eax + SOCKET.Domain], AF_INET4 |
|
- | 680 | jne s_error |
|
- | 681 | ||
- | 682 | cmp [eax + SOCKET.Protocol], IP_PROTO_TCP |
|
- | 683 | jne s_error |
|
- | 684 | ||
104 | call mutex_init |
685 | .loop: |
- | 686 | get_from_queue (eax + SOCKET_QUEUE_LOCATION), MAX_backlog, 4, .block |
|
- | 687 | ||
- | 688 | ; Ok, we got a socket ptr |
|
- | 689 | mov eax, [esi] |
|
- | 690 | ||
105 | mov eax, ebx |
691 | ; Change thread ID to that of the current thread |
- | 692 | mov ebx, [TASK_BASE] |
|
- | 693 | mov ebx, [ebx + TASKDATA.pid] |
|
- | 694 | mov [eax + SOCKET.TID], ebx |
|
- | 695 | ||
- | 696 | ; Convert it to a socket number |
|
- | 697 | call SOCKET_ptr_to_num |
|
- | 698 | jz s_error |
|
- | 699 | ; and return it to caller |
|
- | 700 | mov [esp+32], eax |
|
- | 701 | ret |
|
- | 702 | ||
- | 703 | .block: |
|
- | 704 | test [eax + SOCKET.options], SO_NONBLOCK |
|
- | 705 | jnz s_error |
|
- | 706 | ||
- | 707 | call SOCKET_block |
|
- | 708 | jmp .loop |
|
- | 709 | ||
- | 710 | ;----------------------------------------------------------------- |
|
- | 711 | ; |
|
- | 712 | ; SOCKET_close |
|
- | 713 | ; |
|
- | 714 | ; IN: socket number in ecx |
|
- | 715 | ; OUT: eax is socket num, -1 on error |
|
- | 716 | ; |
|
- | 717 | ;----------------------------------------------------------------- |
|
- | 718 | align 4 |
|
- | 719 | SOCKET_close: |
|
- | 720 | ||
- | 721 | DEBUGF 2,"SOCKET_close: socknum=%u\n", ecx |
|
- | 722 | ||
106 | 723 | call SOCKET_num_to_ptr |
|
- | 724 | jz s_error |
|
- | 725 | ||
- | 726 | mov dword [esp+32], 0 ; The socket exists, so we will succeed in closing it. |
|
- | 727 | ||
- | 728 | .socket: |
|
- | 729 | or [eax + SOCKET.options], SO_NONBLOCK ; Mark the socket as non blocking, we dont want it to block any longer! |
|
- | 730 | ||
- | 731 | test [eax + SOCKET.state], SS_BLOCKED ; Is the socket still in blocked state? |
|
- | 732 | jz @f |
|
- | 733 | call SOCKET_notify.unblock ; Unblock it. |
|
- | 734 | @@: |
|
- | 735 | ||
- | 736 | cmp [eax + SOCKET.Domain], AF_INET4 |
|
- | 737 | jne .free |
|
- | 738 | ||
- | 739 | cmp [eax + SOCKET.Protocol], IP_PROTO_TCP |
|
- | 740 | je .tcp |
|
- | 741 | ||
- | 742 | .free: |
|
- | 743 | call SOCKET_free |
|
- | 744 | ret |
|
- | 745 | ||
- | 746 | .tcp: |
|
- | 747 | cmp [eax + TCP_SOCKET.t_state], TCPS_SYN_RECEIVED ; state must be LISTEN, SYN_SENT or CLOSED |
|
- | 748 | jb .free |
|
- | 749 | ||
- | 750 | call TCP_usrclosed |
|
- | 751 | call TCP_output ;;;; Fixme: is this nescessary?? |
|
- | 752 | ||
- | 753 | ret |
|
- | 754 | ||
- | 755 | ||
- | 756 | ;----------------------------------------------------------------- |
|
- | 757 | ; |
|
- | 758 | ; SOCKET_receive |
|
- | 759 | ; |
|
- | 760 | ; IN: socket number in ecx |
|
- | 761 | ; addr to buffer in edx |
|
- | 762 | ; length of buffer in esi |
|
- | 763 | ; flags in edi |
|
- | 764 | ; OUT: eax is number of bytes copied, -1 on error |
|
- | 765 | ; |
|
107 | ; add socket to the list by changing pointers |
766 | ;----------------------------------------------------------------- |
- | 767 | align 4 |
|
- | 768 | SOCKET_receive: |
|
- | 769 | ||
- | 770 | DEBUGF 2,"SOCKET_receive: socknum=%u bufaddr=%x buflength=%u flags=%x\n", ecx, edx, esi, edi |
|
- | 771 | ||
- | 772 | call SOCKET_num_to_ptr |
|
- | 773 | jz s_error |
|
- | 774 | ||
- | 775 | jmp [eax + SOCKET.rcv_proc] |
|
- | 776 | ||
- | 777 | ||
- | 778 | align 4 |
|
- | 779 | SOCKET_receive_dgram: |
|
- | 780 | ||
- | 781 | DEBUGF 1,"SOCKET_receive: DGRAM\n" |
|
- | 782 | ||
- | 783 | mov ebx, esi |
|
- | 784 | mov edi, edx ; addr to buffer |
|
- | 785 | ||
- | 786 | .loop: |
|
- | 787 | get_from_queue (eax + SOCKET_QUEUE_LOCATION), SOCKET_QUEUE_SIZE, sizeof.socket_queue_entry, .block ; destroys esi and ecx |
|
- | 788 | ||
- | 789 | mov ecx, [esi + socket_queue_entry.data_size] |
|
- | 790 | DEBUGF 1,"SOCKET_receive: %u bytes data\n", ecx |
|
- | 791 | ||
- | 792 | cmp ecx, ebx |
|
- | 793 | ja .too_small |
|
- | 794 | ||
- | 795 | push [esi + socket_queue_entry.buf_ptr] ; save the buffer addr so we can clear it later |
|
- | 796 | mov esi, [esi + socket_queue_entry.data_ptr] |
|
- | 797 | DEBUGF 1,"SOCKET_receive: Source buffer=%x real addr=%x\n", [esp], esi |
|
- | 798 | mov [esp+32+4], ecx ; return number of bytes copied |
|
- | 799 | ||
- | 800 | ; copy the data |
|
- | 801 | shr ecx, 1 |
|
- | 802 | jnc .nb |
|
- | 803 | movsb |
|
Line -... | Line 804... | ||
- | 804 | .nb: |
|
- | 805 | shr ecx, 1 |
|
- | 806 | jnc .nw |
|
- | 807 | movsw |
|
- | 808 | .nw: |
|
- | 809 | test ecx, ecx |
|
- | 810 | jz .nd |
|
- | 811 | rep movsd |
|
- | 812 | .nd: |
|
- | 813 | ||
- | 814 | call kernel_free ; remove the packet |
|
- | 815 | ret |
|
- | 816 | ||
- | 817 | .too_small: |
|
- | 818 | ||
- | 819 | DEBUGF 2,"SOCKET_receive: Buffer too small\n" |
|
- | 820 | jmp s_error |
|
- | 821 | ||
- | 822 | .block: |
|
- | 823 | test [eax + SOCKET.options], SO_NONBLOCK |
|
- | 824 | jnz s_error |
|
- | 825 | ||
- | 826 | call SOCKET_block |
|
108 | mov ebx, net_sockets |
827 | jmp .loop |
109 | push [ebx + SOCKET.NextPtr] |
828 | |
110 | mov [ebx + SOCKET.NextPtr], eax |
829 | |
111 | mov [eax + SOCKET.PrevPtr], ebx |
830 | align 4 |
- | 831 | SOCKET_receive_local: |
|
- | 832 | ||
Line 112... | Line -... | ||
112 | pop ebx |
- | |
113 | mov [eax + SOCKET.NextPtr], ebx |
- | |
114 | or ebx, ebx |
833 | ; does this socket have a PID yet? |
115 | jz @f |
- | |
116 | mov [ebx + SOCKET.PrevPtr], eax |
- | |
- | 834 | cmp [eax + SOCKET.PID], 0 |
|
117 | 835 | jne @f |
|
118 | @@: ; set socket owner PID to the one of calling process |
836 | |
119 | mov ebx, [TASK_BASE] |
- | |
120 | mov ebx, [ebx + TASKDATA.pid] |
- | |
121 | mov [eax + SOCKET.PID], ebx |
- | |
122 | - | ||
123 | ; find first free socket number and use it |
- | |
124 | ;mov edx, ebx |
- | |
125 | mov ebx, net_sockets |
- | |
126 | xor ecx, ecx |
- | |
127 | .next_socket_number: |
- | |
Line 128... | Line -... | ||
128 | inc ecx |
- | |
129 | .next_socket: |
837 | ; Change PID to that of current process |
Line -... | Line 838... | ||
- | 838 | mov ebx, [TASK_BASE] |
|
- | 839 | mov ebx, [ebx + TASKDATA.pid] |
|
- | 840 | mov [eax + SOCKET.PID], ebx |
|
- | 841 | mov [eax + SOCKET.TID], ebx ; currently TID = PID in kolibrios :( |
|
- | 842 | @@: |
|
- | 843 | ||
- | 844 | mov [eax + SOCKET.rcv_proc], SOCKET_receive_stream |
|
130 | mov ebx, [ebx + SOCKET.NextPtr] |
845 | |
- | 846 | align 4 |
|
- | 847 | SOCKET_receive_stream: |
|
- | 848 | ||
- | 849 | DEBUGF 1,"SOCKET_receive: STREAM\n" |
|
- | 850 | ||
- | 851 | mov ebx, edi |
|
- | 852 | mov ecx, esi |
|
- | 853 | mov edi, edx |
|
- | 854 | xor edx, edx |
|
- | 855 | ||
- | 856 | test ebx, MSG_DONTWAIT |
|
131 | or ebx, ebx |
857 | jnz .dontwait |
132 | jz .last_socket_number |
- | |
Line -... | Line 858... | ||
- | 858 | .loop: |
|
- | 859 | cmp [eax + STREAM_SOCKET.rcv + RING_BUFFER.size], 0 |
|
- | 860 | je .block |
|
- | 861 | .dontwait: |
|
- | 862 | test ebx, MSG_PEEK |
|
- | 863 | jnz .peek |
|
133 | cmp [ebx + SOCKET.Number], ecx |
864 | |
- | 865 | add eax, STREAM_SOCKET.rcv |
|
- | 866 | call SOCKET_ring_read |
|
- | 867 | call SOCKET_ring_free |
|
- | 868 | ||
- | 869 | mov [esp+32], ecx ; return number of bytes copied |
|
- | 870 | ret |
|
- | 871 | ||
- | 872 | .peek: |
|
- | 873 | mov ecx, [eax + STREAM_SOCKET.rcv + RING_BUFFER.size] |
|
- | 874 | mov [esp+32], ecx ; return number of bytes available |
|
- | 875 | ret |
|
- | 876 | ||
134 | jne .next_socket |
877 | .block: |
135 | ;cmp [ebx + SOCKET.PID], edx |
878 | test [eax + SOCKET.options], SO_NONBLOCK |
- | 879 | jnz .return0 |
|
136 | ;jne .next_socket |
880 | |
137 | mov ebx, net_sockets |
881 | call SOCKET_block |
138 | jmp .next_socket_number |
882 | jmp .loop |
139 | 883 | ||
140 | .last_socket_number: |
- | |
141 | mov [eax + SOCKET.Number], ecx |
884 | .return0: |
142 | 885 | xor ecx, ecx |
|
- | 886 | mov [esp+32], ecx |
|
- | 887 | ret |
|
- | 888 | ||
- | 889 | ||
Line 143... | Line 890... | ||
143 | .exit: |
890 | ;----------------------------------------------------------------- |
- | 891 | ; |
|
- | 892 | ; SOCKET_send |
|
- | 893 | ; |
|
- | 894 | ; |
|
144 | ret |
895 | ; IN: socket number in ecx |
145 | endp |
896 | ; pointer to data in edx |
- | 897 | ; datalength in esi |
|
146 | 898 | ; flags in edi |
|
- | 899 | ; OUT: -1 on error |
|
- | 900 | ; |
|
- | 901 | ;----------------------------------------------------------------- |
|
147 | ;; Free socket data memory and pop socket off the list |
902 | align 4 |
- | 903 | SOCKET_send: |
|
148 | ; |
904 | |
- | 905 | DEBUGF 2,"SOCKET_send: socknum=%u data ptr=%x length=%u flags=%x\n", ecx, edx, esi, edi |
|
149 | ; @param sockAddr is a socket structure address |
906 | |
150 | ;; |
907 | call SOCKET_num_to_ptr |
151 | proc net_socket_free stdcall uses ebx ecx edx, sockAddr:DWORD |
908 | jz s_error |
152 | mov eax, [sockAddr] |
909 | |
153 | DEBUGF 1, "K : net_socket_free (0x%x)\n", eax |
910 | mov ecx, esi |
- | 911 | mov esi, edx |
|
- | 912 | ||
- | 913 | jmp [eax + SOCKET.snd_proc] |
|
- | 914 | ||
- | 915 | ||
154 | ; check if we got something similar to socket structure address |
916 | align 4 |
Line 155... | Line -... | ||
155 | or eax, eax |
- | |
156 | jz .error |
- | |
157 | - | ||
158 | ; make sure sockAddr is one of the socket addresses in the list |
917 | SOCKET_send_udp: |
159 | mov ebx, net_sockets |
918 | |
160 | ;mov ecx, [TASK_BASE] |
919 | DEBUGF 1,"SOCKET_send: UDP\n" |
161 | ;mov ecx, [ecx + TASKDATA.pid] |
- | |
162 | .next_socket: |
920 | |
- | 921 | mov [esp+32], ecx |
|
- | 922 | call UDP_output |
|
- | 923 | cmp eax, -1 |
|
- | 924 | je s_error |
|
- | 925 | ret |
|
- | 926 | ||
- | 927 | ||
- | 928 | align 4 |
|
- | 929 | SOCKET_send_tcp: |
|
- | 930 | ||
- | 931 | DEBUGF 1,"SOCKET_send: TCP\n" |
|
- | 932 | ||
- | 933 | push eax |
|
- | 934 | add eax, STREAM_SOCKET.snd |
|
- | 935 | call SOCKET_ring_write |
|
- | 936 | pop eax |
|
- | 937 | ||
- | 938 | mov [esp+32], ecx |
|
- | 939 | ||
- | 940 | call TCP_output |
|
- | 941 | ret |
|
- | 942 | ||
- | 943 | ||
- | 944 | align 4 |
|
- | 945 | SOCKET_send_ip: |
|
- | 946 | ||
- | 947 | DEBUGF 1,"SOCKET_send: IPv4\n" |
|
- | 948 | ||
- | 949 | mov [esp+32], ecx |
|
- | 950 | call IPv4_output_raw |
|
- | 951 | cmp eax, -1 |
|
- | 952 | je s_error |
|
- | 953 | ret |
|
- | 954 | ||
- | 955 | ||
- | 956 | align 4 |
|
- | 957 | SOCKET_send_icmp: |
|
- | 958 | ||
- | 959 | DEBUGF 1,"SOCKET_send: ICMP\n" |
|
- | 960 | ||
- | 961 | mov [esp+32], ecx |
|
- | 962 | call ICMP_output_raw |
|
- | 963 | cmp eax, -1 |
|
- | 964 | je s_error |
|
- | 965 | ret |
|
- | 966 | ||
- | 967 | ||
- | 968 | align 4 |
|
- | 969 | SOCKET_send_pppoe: |
|
- | 970 | ||
- | 971 | DEBUGF 1,"SOCKET_send: PPPoE\n" |
|
- | 972 | ||
- | 973 | mov [esp+32], ecx |
|
163 | mov ebx, [ebx + SOCKET.NextPtr] |
974 | mov ebx, [eax + SOCKET.device] |
- | 975 | ||
164 | or ebx, ebx |
976 | call PPPoE_discovery_output |
- | 977 | cmp eax, -1 |
|
- | 978 | je s_error |
|
- | 979 | ret |
|
- | 980 | ||
- | 981 | ||
- | 982 | ||
- | 983 | align 4 |
|
- | 984 | SOCKET_send_local: |
|
- | 985 | ||
- | 986 | ; does this socket have a PID yet? |
|
- | 987 | cmp [eax + SOCKET.PID], 0 |
|
165 | jz .error |
988 | jne @f |
- | 989 | ||
- | 990 | ; Change PID to that of current process |
|
- | 991 | mov ebx, [TASK_BASE] |
|
- | 992 | mov ebx, [ebx + TASKDATA.pid] |
|
- | 993 | mov [eax + SOCKET.PID], ebx |
|
- | 994 | mov [eax + SOCKET.TID], ebx ; currently TID = PID in kolibrios :( |
|
- | 995 | @@: |
|
- | 996 | mov [eax + SOCKET.snd_proc], SOCKET_send_local_ |
|
- | 997 | ||
- | 998 | align 4 |
|
- | 999 | SOCKET_send_local_: |
|
- | 1000 | ||
- | 1001 | DEBUGF 1,"SOCKET_send: LOCAL\n" |
|
- | 1002 | ||
- | 1003 | ; get the other side's socket and check if it still exists |
|
- | 1004 | mov eax, [eax + SOCKET.device] |
|
- | 1005 | call SOCKET_check |
|
- | 1006 | jz s_error |
|
- | 1007 | ||
- | 1008 | ; allright, shove in the data! |
|
- | 1009 | push eax |
|
- | 1010 | add eax, STREAM_SOCKET.rcv |
|
- | 1011 | call SOCKET_ring_write |
|
- | 1012 | pop eax |
|
- | 1013 | ||
- | 1014 | ; return the number of written bytes (or errorcode) to application |
|
- | 1015 | mov [esp+32], ecx |
|
- | 1016 | ||
- | 1017 | ; and notify the other end |
|
- | 1018 | call SOCKET_notify |
|
- | 1019 | ||
- | 1020 | ret |
|
- | 1021 | ||
- | 1022 | ||
- | 1023 | ;----------------------------------------------------------------- |
|
- | 1024 | ; |
|
- | 1025 | ; SOCKET_get_options |
|
- | 1026 | ; |
|
- | 1027 | ; IN: ecx = socket number |
|
- | 1028 | ; edx = pointer to the options: |
|
- | 1029 | ; dd level, optname, optval, optlen |
|
- | 1030 | ; OUT: -1 on error |
|
- | 1031 | ; |
|
- | 1032 | ; At moment, uses only pseudo-optname -2 for get last_ack_number for TCP. |
|
- | 1033 | ; TODO: find best way to notify that send()'ed data were acknowledged |
|
- | 1034 | ; Also pseudo-optname -3 is valid and returns socket state, one of TCPS_*. |
|
- | 1035 | ; |
|
- | 1036 | ;----------------------------------------------------------------- |
|
- | 1037 | align 4 |
|
- | 1038 | SOCKET_get_opt: |
|
- | 1039 | ||
- | 1040 | DEBUGF 2,"SOCKET_get_opt\n" |
|
- | 1041 | ||
- | 1042 | call SOCKET_num_to_ptr |
|
- | 1043 | jz s_error |
|
- | 1044 | ||
- | 1045 | cmp dword [edx], IP_PROTO_TCP |
|
- | 1046 | jne s_error |
|
- | 1047 | cmp dword [edx+4], -2 |
|
- | 1048 | je @f |
|
166 | cmp ebx, eax |
1049 | cmp dword [edx+4], -3 |
- | 1050 | jne s_error |
|
- | 1051 | @@: |
|
167 | jne .next_socket |
1052 | ; mov eax, [edx+12] |
168 | ;cmp [ebx + SOCKET.PID], ecx |
1053 | ; test eax, eax |
169 | ;jne .next_socket |
1054 | ; jz .fail |
- | 1055 | ; cmp dword [eax], 4 |
|
- | 1056 | ; mov dword [eax], 4 |
|
- | 1057 | ; jb .fail |
|
- | 1058 | ; stdcall net_socket_num_to_addr, ecx |
|
- | 1059 | ; test eax, eax |
|
Line -... | Line 1060... | ||
- | 1060 | ; jz .fail |
|
- | 1061 | ; ; todo: check that eax is really TCP socket |
|
- | 1062 | ; mov ecx, [eax + TCP_SOCKET.last_ack_number] |
|
- | 1063 | ; cmp dword [edx+4], -2 |
|
- | 1064 | ; jz @f |
|
- | 1065 | ; mov ecx, [eax + TCP_SOCKET.state] |
|
170 | 1066 | @@: |
|
- | 1067 | mov eax, [edx+8] |
|
- | 1068 | test eax, eax |
|
- | 1069 | jz @f |
|
- | 1070 | mov [eax], ecx |
|
- | 1071 | @@: |
|
- | 1072 | mov dword [esp+32], 0 |
|
- | 1073 | ret |
|
- | 1074 | ||
171 | ; okay, we found the correct one |
1075 | |
- | 1076 | ||
- | 1077 | ;----------------------------------------------------------------- |
|
- | 1078 | ; |
|
- | 1079 | ; SOCKET_set_options |
|
- | 1080 | ; |
|
- | 1081 | ; IN: ecx = socket number |
|
- | 1082 | ; edx = pointer to the options: |
|
- | 1083 | ; dd level, optname, optlen, optval |
|
- | 1084 | ; OUT: -1 on error |
|
- | 1085 | ; |
|
- | 1086 | ;----------------------------------------------------------------- |
|
- | 1087 | align 4 |
|
- | 1088 | SOCKET_set_opt: |
|
- | 1089 | ||
- | 1090 | DEBUGF 2,"SOCKET_set_opt\n" |
|
- | 1091 | ||
- | 1092 | call SOCKET_num_to_ptr |
|
- | 1093 | jz s_error |
|
- | 1094 | ||
- | 1095 | cmp dword [edx], SOL_SOCKET |
|
- | 1096 | jne s_error |
|
- | 1097 | ||
- | 1098 | cmp dword [edx+4], SO_BINDTODEVICE |
|
- | 1099 | je .bind |
|
- | 1100 | ||
- | 1101 | cmp dword [edx+4], SO_BLOCK |
|
- | 1102 | je .block |
|
- | 1103 | ||
- | 1104 | jmp s_error |
|
172 | ; mark local port as unused |
1105 | |
Line 173... | Line 1106... | ||
173 | movzx ebx, [eax + SOCKET.LocalPort] |
1106 | .bind: |
174 | push eax |
1107 | cmp dword [edx+8], 0 |
- | 1108 | je .unbind |
|
- | 1109 | ||
175 | mov eax, [network_free_ports] |
1110 | movzx edx, byte [edx + 9] |
176 | xchg bl, bh |
- | |
Line 177... | Line -... | ||
177 | lock bts [eax], ebx |
- | |
178 | pop eax |
- | |
179 | ; remove it from the list first, changing pointers |
- | |
180 | mov ebx, [eax + SOCKET.NextPtr] |
1111 | cmp edx, MAX_NET_DEVICES |
181 | mov eax, [eax + SOCKET.PrevPtr] |
- | |
182 | mov [eax + SOCKET.NextPtr], ebx |
- | |
183 | or ebx, ebx |
- | |
184 | jz @f |
- | |
185 | mov [ebx + SOCKET.PrevPtr], eax |
- | |
186 | 1112 | ja s_error |
|
187 | @@: ; and finally free the memory structure used |
- | |
188 | stdcall kernel_free, [sockAddr] |
- | |
189 | ret |
1113 | |
Line 190... | Line -... | ||
190 | - | ||
191 | .error: |
- | |
192 | DEBUGF 1, "K : failed\n" |
- | |
193 | ret |
- | |
194 | endp |
- | |
195 | - | ||
196 | ;; Get socket structure address by its number |
- | |
197 | ; Scan through sockets list to find the socket with specified number. |
- | |
198 | ; This proc uses SOCKET.PID indirectly to check if socket is owned by |
1114 | mov edx, [NET_DRV_LIST + 4*edx] |
199 | ; calling process. |
- | |
200 | ; |
- | |
201 | ; @param sockNum is a socket number |
- | |
Line 202... | Line 1115... | ||
202 | ; @return socket structure address or 0 (not found) in EAX |
1115 | test edx, edx |
203 | ;; |
- | |
204 | proc net_socket_num_to_addr stdcall uses ebx ecx, sockNum:DWORD |
1116 | jz s_error |
Line 205... | Line 1117... | ||
205 | mov eax, [sockNum] |
1117 | mov [eax + SOCKET.device], edx |
206 | ; check if we got something similar to socket number |
1118 | |
- | 1119 | DEBUGF 1,"SOCKET_set_opt: Bound socket %x to device %x\n",eax, edx |
|
- | 1120 | ||
207 | or eax, eax |
1121 | mov dword [esp+32], 0 ; success! |
208 | jz .error |
- | |
Line 209... | Line -... | ||
209 | - | ||
210 | ; scan through sockets list |
- | |
211 | mov ebx, net_sockets |
- | |
212 | ;mov ecx, [TASK_BASE] |
- | |
213 | ;mov ecx, [ecx + TASKDATA.pid] |
- | |
214 | .next_socket: |
- | |
215 | mov ebx, [ebx + SOCKET.NextPtr] |
- | |
216 | or ebx, ebx |
- | |
217 | jz .error |
- | |
218 | cmp [ebx + SOCKET.Number], eax |
- | |
219 | jne .next_socket |
- | |
220 | ;cmp [ebx + SOCKET.PID], ecx |
- | |
221 | ;jne .next_socket |
- | |
Line -... | Line 1122... | ||
- | 1122 | ret |
|
- | 1123 | ||
- | 1124 | .unbind: |
|
- | 1125 | mov [eax + SOCKET.device], 0 |
|
- | 1126 | ||
- | 1127 | mov dword [esp+32], 0 ; success! |
|
- | 1128 | ret |
|
- | 1129 | ||
- | 1130 | .block: |
|
222 | 1131 | cmp dword [edx+8], 0 |
|
- | 1132 | je .unblock |
|
- | 1133 | ||
- | 1134 | and [eax + SOCKET.options], not SO_NONBLOCK |
|
- | 1135 | ||
- | 1136 | mov dword [esp+32], 0 ; success! |
|
- | 1137 | ret |
|
- | 1138 | ||
223 | ; okay, we found the correct one |
1139 | .unblock: |
224 | mov eax, ebx |
1140 | or [eax + SOCKET.options], SO_NONBLOCK |
- | 1141 | ||
- | 1142 | mov dword [esp+32], 0 ; success! |
|
225 | ret |
1143 | ret |
226 | 1144 | ||
- | 1145 | ||
- | 1146 | ||
- | 1147 | ;----------------------------------------------------------------- |
|
227 | .error: |
1148 | ; |
228 | xor eax, eax |
1149 | ; SOCKET_pair |
- | 1150 | ; |
|
- | 1151 | ; Allocates a pair of linked LOCAL domain sockets |
|
229 | ret |
1152 | ; |
- | 1153 | ; IN: / |
|
- | 1154 | ; OUT: eax is socket1 num, -1 on error |
|
- | 1155 | ; ebx is socket2 num |
|
- | 1156 | ; |
|
- | 1157 | ;----------------------------------------------------------------- |
|
- | 1158 | align 4 |
|
- | 1159 | SOCKET_pair: |
|
230 | endp |
1160 | |
- | 1161 | DEBUGF 2,"SOCKET_pair\n" |
|
- | 1162 | ||
231 | 1163 | call SOCKET_alloc |
|
232 | ;; Get socket number by its structure address |
1164 | jz s_error |
- | 1165 | mov [esp+32], edi ; application's eax |
|
- | 1166 | ||
- | 1167 | mov [eax + SOCKET.Domain], AF_LOCAL |
|
- | 1168 | mov [eax + SOCKET.Type], SOCK_STREAM |
|
- | 1169 | mov [eax + SOCKET.Protocol], 0 ;;; CHECKME |
|
233 | ; Scan through sockets list to find the socket with specified address. |
1170 | mov [eax + SOCKET.snd_proc], SOCKET_send_local |
- | 1171 | mov [eax + SOCKET.rcv_proc], SOCKET_receive_local |
|
Line 234... | Line -... | ||
234 | ; This proc uses SOCKET.PID indirectly to check if socket is owned by |
- | |
235 | ; calling process. |
- | |
236 | ; |
1172 | mov [eax + SOCKET.PID], 0 |
Line 237... | Line 1173... | ||
237 | ; @param sockAddr is a socket structure address |
1173 | mov ebx, eax |
238 | ; @return socket number (SOCKET.Number) or 0 (not found) in EAX |
1174 | |
- | 1175 | call SOCKET_alloc |
|
- | 1176 | jz .error |
|
- | 1177 | mov [esp+24], edi ; application's ebx |
|
- | 1178 | ||
- | 1179 | mov [eax + SOCKET.Domain], AF_LOCAL |
|
- | 1180 | mov [eax + SOCKET.Type], SOCK_STREAM |
|
- | 1181 | mov [eax + SOCKET.Protocol], 0 ;;; CHECKME |
|
- | 1182 | mov [eax + SOCKET.snd_proc], SOCKET_send_local |
|
- | 1183 | mov [eax + SOCKET.rcv_proc], SOCKET_receive_local |
|
- | 1184 | mov [eax + SOCKET.PID], 0 |
|
- | 1185 | ||
- | 1186 | ; Link the two sockets to eachother |
|
- | 1187 | mov [eax + SOCKET.device], ebx |
|
- | 1188 | mov [ebx + SOCKET.device], eax |
|
- | 1189 | ||
- | 1190 | lea eax, [eax + STREAM_SOCKET.rcv] |
|
- | 1191 | call SOCKET_ring_create |
|
- | 1192 | ||
- | 1193 | lea eax, [ebx + STREAM_SOCKET.rcv] |
|
- | 1194 | call SOCKET_ring_create |
|
- | 1195 | pop eax |
|
- | 1196 | ||
- | 1197 | ret |
|
- | 1198 | ||
- | 1199 | .error: |
|
- | 1200 | mov eax, ebx |
|
- | 1201 | call SOCKET_free |
|
- | 1202 | jmp s_error |
|
- | 1203 | ||
- | 1204 | ||
- | 1205 | ||
- | 1206 | ;----------------------------------------------------------------- |
|
- | 1207 | ; |
|
- | 1208 | ; SOCKET_debug |
|
239 | ;; |
1209 | ; |
240 | proc net_socket_addr_to_num stdcall uses ebx ecx, sockAddr:DWORD |
- | |
Line 241... | Line -... | ||
241 | mov eax, [sockAddr] |
- | |
242 | ; check if we got something similar to socket structure address |
- | |
243 | or eax, eax |
- | |
244 | jz .error |
- | |
245 | - | ||
246 | ; scan through sockets list |
- | |
247 | mov ebx, net_sockets |
- | |
248 | ;mov ecx, [TASK_BASE] |
- | |
249 | ;mov ecx, [ecx + TASKDATA.pid] |
- | |
250 | .next_socket: |
- | |
251 | mov ebx, [ebx + SOCKET.NextPtr] |
- | |
252 | or ebx, ebx |
- | |
253 | jz .error |
- | |
254 | cmp ebx, eax |
- | |
255 | jne .next_socket |
1210 | ; Copies socket variables to application buffer |
256 | ;cmp [ebx + SOCKET.PID], ecx |
1211 | ; |
257 | ;jne .next_socket |
- | |
258 | - | ||
259 | ; okay, we found the correct one |
- | |
260 | mov eax, [ebx + SOCKET.Number] |
- | |
261 | ret |
1212 | ; IN: ecx = socket number |
262 | - | ||
263 | .error: |
- | |
264 | xor eax, eax |
- | |
265 | ret |
- | |
266 | endp |
- | |
267 | - | ||
268 | ;; [53.9] Check if local port is used by any socket in the system. |
- | |
269 | ; Scan through sockets list, checking SOCKET.LocalPort. |
- | |
270 | ; Useful when you want a to generate a unique local port number. |
- | |
271 | ; This proc doesn't guarantee that after calling it and trying to use |
- | |
272 | ; the port reported being free in calls to socket_open/socket_open_tcp it'll |
- | |
273 | ; still be free or otherwise it'll still be used if reported being in use. |
1213 | ; edx = pointer to buffer |
274 | ; |
- | |
275 | ; @param BX is a port number |
- | |
276 | ; @return 1 (port is free) or 0 (port is in use) in EAX |
1214 | ; |
277 | ;; |
- | |
278 | proc is_localport_unused stdcall |
- | |
279 | movzx ebx, bx |
- | |
280 | mov eax, [network_free_ports] |
- | |
281 | bt [eax], ebx |
- | |
282 | setc al |
- | |
283 | movzx eax, al |
- | |
284 | ret |
- | |
285 | endp |
- | |
286 | - | ||
287 | ;====================================== |
- | |
288 | set_local_port: |
- | |
289 | ;-------------------------------------- |
- | |
290 | ;? Set local port in socket structure. |
1215 | ; OUT: -1 on error |
291 | ;-------------------------------------- |
- | |
292 | ;> eax -> struct SOCKET |
- | |
293 | ;> bx = local port, or 0 if the kernel must select it itself |
- | |
294 | ;-------------------------------------- |
- | |
295 | ;< CF set on error / cleared on success |
- | |
296 | ;< [eax+SOCKET.LocalPort] filled on success |
- | |
297 | ;====================================== |
- | |
298 | ; 0. Prepare: save registers, make eax point to ports table, expand port to ebx. |
- | |
299 | push eax ecx |
- | |
300 | mov eax, [network_free_ports] |
1216 | ;----------------------------------------------------------------- |
301 | movzx ebx, bx |
- | |
302 | ; 1. Test, whether the kernel should choose port itself. If no, proceed to 5. |
- | |
303 | test ebx, ebx |
- | |
304 | jnz .given |
- | |
305 | ; 2. Yes, it should. Set ecx = limit of table, eax = start value |
- | |
306 | lea ecx, [eax+0x10000/8] |
- | |
307 | add eax, [network_free_hint] |
- | |
308 | ; 3. First scan loop: from free hint to end of table. |
- | |
309 | .scan1: |
- | |
310 | ; 3a. For each dword, find bit set to 1 |
- | |
311 | bsf ebx, [eax] |
- | |
312 | jz .next1 |
- | |
313 | ; 3b. If such bit has been found, atomically test again and clear it. |
- | |
314 | lock btr [eax], ebx |
- | |
315 | ; 3c. If the bit was still set (usual case), we have found and reserved one port. |
- | |
316 | ; Proceed to 6. |
- | |
317 | jc .found |
- | |
318 | ; 3d. Otherwise, someone has reserved it between bsf and btr, so retry search. |
- | |
319 | jmp .scan1 |
- | |
320 | .next1: |
- | |
321 | ; 3e. All bits are cleared, so advance to next dword. |
1217 | align 4 |
322 | add eax, 4 |
- | |
323 | ; 3f. Check limit and continue loop. |
- | |
324 | cmp eax, ecx |
- | |
325 | jb .scan1 |
- | |
326 | ; 4. Second scan loop: from port 1024 (start of non-system ports) to free hint. |
- | |
327 | mov eax, [network_free_ports] |
- | |
328 | mov ecx, eax |
1218 | SOCKET_debug: |
329 | add ecx, [network_free_hint] |
- | |
330 | add eax, 1024/8 |
- | |
331 | ; 4a. Test whether there is something to scan. |
1219 | |
332 | cmp eax, ecx |
- | |
333 | jae .fail |
- | |
334 | ; 4b. Enter the loop, the process is same as for 3. |
- | |
335 | .scan2: |
- | |
336 | bsf ebx, [eax] |
1220 | DEBUGF 1,"SOCKET_debug\n" |
337 | jz .next2 |
- | |
338 | lock btr [eax], ebx |
1221 | |
339 | jc .found |
- | |
340 | jmp .scan2 |
1222 | mov edi, edx |
341 | .next2: |
1223 | |
342 | add eax, 4 |
- | |
343 | cmp eax, ecx |
- | |
344 | jb .scan2 |
- | |
345 | ; 4c. None found. Fail. |
- | |
346 | .fail: |
- | |
347 | pop ecx eax |
- | |
348 | stc |
1224 | test ecx, ecx |
Line 349... | Line -... | ||
349 | ret |
- | |
350 | ; 5. No, the kernel should reserve selected port. |
- | |
351 | .given: |
- | |
352 | ; 5a. Atomically test old value and clear bit. |
- | |
353 | lock btr [eax], ebx |
- | |
354 | ; 5b. If the bit was set, reservation is successful. Proceed to 8. |
- | |
355 | jc .set |
- | |
356 | ; 5c. Otherwise, fail. |
- | |
357 | jmp .fail |
- | |
358 | .found: |
- | |
359 | ; 6. We have found the bit set to 1, convert the position to port number. |
- | |
Line -... | Line 1225... | ||
- | 1225 | jz .returnall |
|
- | 1226 | ||
- | 1227 | call SOCKET_num_to_ptr |
|
- | 1228 | jz s_error |
|
- | 1229 | ||
- | 1230 | mov esi, eax |
|
- | 1231 | mov ecx, SOCKETBUFFSIZE/4 |
|
- | 1232 | rep movsd |
|
- | 1233 | ||
- | 1234 | mov dword [esp+32], 0 |
|
- | 1235 | ret |
|
- | 1236 | ||
- | 1237 | .returnall: |
|
- | 1238 | mov ebx, net_sockets |
|
- | 1239 | .next_socket: |
|
360 | sub eax, [network_free_ports] |
1240 | mov ebx, [ebx + SOCKET.NextPtr] |
Line 361... | Line 1241... | ||
361 | lea ebx, [ebx+eax*8] |
1241 | test ebx, ebx |
Line 362... | Line -... | ||
362 | ; 7. Update free hint. |
- | |
363 | add eax, 4 |
- | |
364 | cmp eax, 65536/8 |
- | |
365 | jb @f |
1242 | jz .done |
366 | mov eax, 1024/8 |
1243 | mov eax, [ebx + SOCKET.Number] |
367 | @@: |
- | |
368 | mov [network_free_hint], eax |
- | |
Line 369... | Line 1244... | ||
369 | .set: |
1244 | stosd |
- | 1245 | jmp .next_socket |
|
- | 1246 | .done: |
|
370 | ; 8. Restore eax, set SOCKET.LocalPort and return. |
1247 | xor eax, eax |
371 | pop ecx eax |
1248 | stosd |
Line 372... | Line 1249... | ||
372 | xchg bl, bh ; Intel -> network byte order |
1249 | |
- | 1250 | mov dword [esp+32], 0 |
|
- | 1251 | ret |
|
373 | mov [eax + SOCKET.LocalPort], bx |
1252 | |
Line 374... | Line -... | ||
374 | clc |
- | |
375 | ret |
- | |
376 | 1253 | ||
377 | ;; [53.0] Open DGRAM socket (connectionless, unreliable) |
1254 | ;----------------------------------------------------------------- |
378 | ; |
- | |
Line -... | Line 1255... | ||
- | 1255 | ; |
|
- | 1256 | ; SOCKET_find_port |
|
- | 1257 | ; |
|
- | 1258 | ; Fills in the local port number for TCP and UDP sockets |
|
- | 1259 | ; This procedure always works because the number of sockets is |
|
- | 1260 | ; limited to a smaller number then the number of possible ports |
|
- | 1261 | ; |
|
- | 1262 | ; IN: eax = socket pointer |
|
- | 1263 | ; OUT: / |
|
- | 1264 | ; |
|
- | 1265 | ;----------------------------------------------------------------- |
|
- | 1266 | align 4 |
|
- | 1267 | SOCKET_find_port: |
|
- | 1268 | ||
- | 1269 | DEBUGF 2,"SOCKET_find_port\n" |
|
- | 1270 | ||
- | 1271 | push ebx esi ecx |
|
- | 1272 | ||
- | 1273 | cmp [eax + SOCKET.Protocol], IP_PROTO_UDP |
|
- | 1274 | je .udp |
|
- | 1275 | ||
- | 1276 | cmp [eax + SOCKET.Protocol], IP_PROTO_TCP |
|
- | 1277 | je .tcp |
|
- | 1278 | ||
- | 1279 | pop ecx esi ebx |
|
- | 1280 | ret |
|
- | 1281 | ||
- | 1282 | .udp: |
|
- | 1283 | mov bx, [last_UDP_port] |
|
379 | ; @param BX is local port number |
1284 | call .findit |
380 | ; @param CX is remote port number |
1285 | mov [last_UDP_port], bx |
381 | ; @param EDX is remote IP address |
1286 | |
382 | ; @return socket number or -1 (error) in EAX |
1287 | pop ecx esi ebx |
- | 1288 | ret |
|
383 | ;; |
1289 | |
384 | proc socket_open stdcall |
- | |
385 | call net_socket_alloc |
- | |
386 | or eax, eax |
1290 | .tcp: |
- | 1291 | mov bx, [last_TCP_port] |
|
387 | jz .error |
1292 | call .findit |
388 | 1293 | mov [last_TCP_port], bx |
|
Line 389... | Line 1294... | ||
389 | DEBUGF 1, "K : socket_open (0x%x)\n", eax |
1294 | |
390 | - | ||
Line 391... | Line -... | ||
391 | push eax |
- | |
392 | 1295 | pop ecx esi ebx |
|
393 | call set_local_port |
1296 | ret |
394 | jc .error.free |
1297 | |
Line 395... | Line 1298... | ||
395 | xchg ch, cl |
1298 | |
396 | mov [eax + SOCKET.RemotePort], cx |
1299 | .restart: |
397 | mov ebx, [stack_ip] |
1300 | mov bx, MIN_EPHEMERAL_PORT_N |
398 | mov [eax + SOCKET.LocalIP], ebx |
1301 | .findit: |
399 | mov [eax + SOCKET.RemoteIP], edx |
- | |
400 | - | ||
- | 1302 | cmp bx, MAX_EPHEMERAL_PORT_N |
|
401 | ;pop eax ; Get the socket number back, so we can return it |
1303 | je .restart |
402 | stdcall net_socket_addr_to_num |
1304 | |
Line 403... | Line 1305... | ||
403 | ret |
1305 | add bh, 1 |
404 | - | ||
405 | .error.free: |
- | |
406 | stdcall net_socket_free;, eax |
1306 | adc bl, 0 |
Line 407... | Line 1307... | ||
407 | 1307 | ||
408 | .error: |
1308 | call SOCKET_check_port |
Line 409... | Line -... | ||
409 | DEBUGF 1, "K : socket_open (fail)\n" |
- | |
410 | or eax, -1 |
1309 | jz .findit |
411 | ret |
- | |
412 | endp |
1310 | ret |
Line -... | Line 1311... | ||
- | 1311 | ||
- | 1312 | ||
413 | 1313 | ||
- | 1314 | ;----------------------------------------------------------------- |
|
- | 1315 | ; |
|
Line 414... | Line -... | ||
414 | ;; [53.5] Open STREAM socket (connection-based, sequenced, reliable, two-way) |
- | |
Line 415... | Line -... | ||
415 | ; |
- | |
416 | ; @param BX is local port number |
- | |
Line -... | Line 1316... | ||
- | 1316 | ; SOCKET_check_port (to be used with AF_INET only!) |
|
- | 1317 | ; |
|
- | 1318 | ; Checks if a local port number is unused |
|
- | 1319 | ; If the proposed port number is unused, it is filled in in the socket structure |
|
417 | ; @param CX is remote port number |
1320 | ; |
- | 1321 | ; IN: eax = socket ptr (to find out if its a TCP/UDP socket) |
|
418 | ; @param EDX is remote IP address |
1322 | ; bx = proposed socket number (network byte order) |
- | 1323 | ; |
|
419 | ; @param ESI is open mode (SOCKET_ACTIVE, SOCKET_PASSIVE) |
1324 | ; OUT: ZF = set on error |
420 | ; @return socket number or -1 (error) in EAX |
1325 | ; |
421 | ;; |
1326 | ;----------------------------------------------------------------- |
422 | proc socket_open_tcp stdcall |
1327 | align 4 |
423 | local sockAddr dd ? |
1328 | SOCKET_check_port: |
- | 1329 | ||
- | 1330 | DEBUGF 2,"SOCKET_check_port: " |
|
- | 1331 | ||
424 | 1332 | mov ecx, [eax + SOCKET.Protocol] |
|
- | 1333 | mov edx, [eax + IP_SOCKET.LocalIP] |
|
425 | cmp esi, SOCKET_PASSIVE |
1334 | mov esi, net_sockets |
Line 426... | Line -... | ||
426 | jne .skip_port_check |
- | |
427 | - | ||
428 | push ebx |
- | |
429 | mov eax, ebx |
- | |
430 | xchg al, ah |
- | |
431 | mov ebx, net_sockets |
1335 | |
Line 432... | Line 1336... | ||
432 | 1336 | .next_socket: |
|
433 | .next_socket: |
1337 | mov esi, [esi + SOCKET.NextPtr] |
- | 1338 | or esi, esi |
|
Line 434... | Line 1339... | ||
434 | mov ebx, [ebx + SOCKET.NextPtr] |
1339 | jz .port_ok |
435 | or ebx, ebx |
- | |
436 | jz .last_socket |
- | |
437 | cmp [ebx + SOCKET.TCBState], TCB_LISTEN |
- | |
438 | jne .next_socket |
- | |
Line 439... | Line 1340... | ||
439 | cmp [ebx + SOCKET.LocalPort], ax |
1340 | |
- | 1341 | cmp [esi + SOCKET.Protocol], ecx |
|
Line 440... | Line 1342... | ||
440 | jne .next_socket |
1342 | jne .next_socket |
441 | 1343 | ||
442 | xchg al, ah |
1344 | cmp [esi + IP_SOCKET.LocalIP], edx |
- | 1345 | jne .next_socket |
|
Line 443... | Line -... | ||
443 | DEBUGF 1, "K : error: port %u is listened by 0x%x\n", ax, ebx |
- | |
444 | pop ebx |
- | |
445 | jmp .error |
- | |
446 | - | ||
447 | .last_socket: |
1346 | |
448 | pop ebx |
- | |
Line 449... | Line 1347... | ||
449 | 1347 | cmp [esi + UDP_SOCKET.LocalPort], bx |
|
450 | .skip_port_check: |
- | |
451 | call net_socket_alloc |
1348 | jne .next_socket |
452 | or eax, eax |
- | |
Line -... | Line 1349... | ||
- | 1349 | ||
- | 1350 | DEBUGF 2,"local port %x already in use\n", bx ; FIXME: find a way to print big endian values with debugf |
|
453 | jz .error |
1351 | ret |
- | 1352 | ||
Line 454... | Line -... | ||
454 | - | ||
455 | DEBUGF 1, "K : socket_open_tcp (0x%x)\n", eax |
1353 | .port_ok: |
456 | 1354 | DEBUGF 2,"local port %x is free\n", bx ; FIXME: find a way to print big endian values with debugf |
|
Line 457... | Line -... | ||
457 | mov [sockAddr], eax |
- | |
458 | - | ||
459 | ; TODO - check this works! |
- | |
460 | ;mov [eax + SOCKET.wndsizeTimer], 0 ; Reset the window timer. |
1355 | mov [eax + UDP_SOCKET.LocalPort], bx |
Line 461... | Line -... | ||
461 | - | ||
462 | call set_local_port |
- | |
Line -... | Line 1356... | ||
- | 1356 | or bx, bx ; clear the zero-flag |
|
- | 1357 | ret |
|
- | 1358 | ||
- | 1359 | ||
- | 1360 | ||
- | 1361 | ;----------------------------------------------------------------- |
|
- | 1362 | ; |
|
- | 1363 | ; SOCKET_input |
|
- | 1364 | ; |
|
- | 1365 | ; Updates a (stateless) socket with received data |
|
- | 1366 | ; |
|
- | 1367 | ; Note: the mutex should already be set ! |
|
- | 1368 | ; |
|
- | 1369 | ; IN: eax = socket ptr |
|
- | 1370 | ; ecx = data size |
|
- | 1371 | ; esi = ptr to data |
|
- | 1372 | ; [esp] = ptr to buf |
|
- | 1373 | ; [esp + 4] = buf size |
|
- | 1374 | ; |
|
463 | jc .error.free |
1375 | ; OUT: / |
- | 1376 | ; |
|
- | 1377 | ;----------------------------------------------------------------- |
|
- | 1378 | align 4 |
|
- | 1379 | SOCKET_input: |
|
- | 1380 | ||
- | 1381 | DEBUGF 2,"SOCKET_input: socket=%x, data=%x size=%u\n", eax, esi, ecx |
|
464 | xchg ch, cl |
1382 | |
465 | mov [eax + SOCKET.RemotePort], cx |
1383 | mov [esp+4], ecx |
- | 1384 | push esi |
|
- | 1385 | mov esi, esp |
|
466 | mov [eax + SOCKET.OrigRemotePort], cx |
1386 | |
467 | mov ebx, [stack_ip] |
- | |
Line 468... | Line 1387... | ||
468 | mov [eax + SOCKET.LocalIP], ebx |
1387 | add_to_queue (eax + SOCKET_QUEUE_LOCATION), SOCKET_QUEUE_SIZE, sizeof.socket_queue_entry, SOCKET_input.full |
469 | mov [eax + SOCKET.RemoteIP], edx |
1388 | |
470 | mov [eax + SOCKET.OrigRemoteIP], edx |
1389 | DEBUGF 1,"SOCKET_input: success\n" |
- | 1390 | add esp, sizeof.socket_queue_entry |
|
471 | 1391 | ||
472 | mov ebx, TCB_LISTEN |
1392 | pusha |
473 | cmp esi, SOCKET_PASSIVE |
1393 | lea ecx, [eax + SOCKET.mutex] |
474 | je @f |
1394 | call mutex_unlock |
475 | mov ebx, TCB_SYN_SENT |
1395 | popa |
- | 1396 | ||
476 | @@: |
1397 | jmp SOCKET_notify |
- | 1398 | ||
- | 1399 | .full: |
|
- | 1400 | DEBUGF 2,"SOCKET_input: socket %x is full!\n", eax |
|
477 | mov [eax + SOCKET.TCBState], ebx ; Indicate the state of the TCB |
1401 | |
Line 478... | Line 1402... | ||
478 | 1402 | pusha |
|
Line -... | Line 1403... | ||
- | 1403 | lea ecx, [eax + SOCKET.mutex] |
|
- | 1404 | call mutex_unlock |
|
- | 1405 | popa |
|
- | 1406 | ||
- | 1407 | call kernel_free |
|
- | 1408 | add esp, 8 |
|
- | 1409 | ||
- | 1410 | ret |
|
- | 1411 | ||
- | 1412 | ||
- | 1413 | ;-------------------------- |
|
479 | cmp ebx, TCB_LISTEN |
1414 | ; |
- | 1415 | ; eax = ptr to ring struct (just a buffer of the right size) |
|
- | 1416 | ; |
|
- | 1417 | align 4 |
|
- | 1418 | SOCKET_ring_create: |
|
- | 1419 | ||
- | 1420 | push esi |
|
- | 1421 | mov esi, eax |
|
- | 1422 | ||
- | 1423 | push edx |
|
- | 1424 | stdcall create_ring_buffer, SOCKET_MAXDATA, PG_SW |
|
- | 1425 | pop edx |
|
- | 1426 | ||
- | 1427 | DEBUGF 1,"SOCKET_ring_created: %x\n", eax |
|
- | 1428 | ||
- | 1429 | pusha |
|
- | 1430 | lea ecx, [esi + RING_BUFFER.mutex] |
|
- | 1431 | call mutex_init |
|
- | 1432 | popa |
|
- | 1433 | ||
- | 1434 | mov [esi + RING_BUFFER.start_ptr], eax |
|
- | 1435 | mov [esi + RING_BUFFER.write_ptr], eax |
|
- | 1436 | mov [esi + RING_BUFFER.read_ptr], eax |
|
- | 1437 | mov [esi + RING_BUFFER.size], 0 |
|
- | 1438 | add eax, SOCKET_MAXDATA |
|
- | 1439 | mov [esi + RING_BUFFER.end_ptr], eax |
|
480 | je .exit |
1440 | mov eax, esi |
- | 1441 | pop esi |
|
- | 1442 | ||
- | 1443 | ret |
|
- | 1444 | ||
- | 1445 | ;----------------------------------------------------------------- |
|
- | 1446 | ; |
|
- | 1447 | ; SOCKET_ring_write |
|
- | 1448 | ; |
|
- | 1449 | ; Adds data to a stream socket, and updates write pointer and size |
|
- | 1450 | ; |
|
- | 1451 | ; IN: eax = ptr to ring struct |
|
- | 1452 | ; ecx = data size |
|
Line 481... | Line -... | ||
481 | - | ||
482 | ; Now, if we are in active mode, then we have to send a SYN to the specified remote port |
- | |
483 | mov eax, EMPTY_QUEUE |
- | |
484 | call dequeue |
1453 | ; esi = ptr to data |
485 | cmp ax, NO_BUFFER |
- | |
Line -... | Line 1454... | ||
- | 1454 | ; |
|
- | 1455 | ; OUT: ecx = number of bytes stored |
|
- | 1456 | ; |
|
- | 1457 | ;----------------------------------------------------------------- |
|
486 | je .exit |
1458 | align 4 |
487 | 1459 | SOCKET_ring_write: |
|
- | 1460 | ||
488 | push eax |
1461 | DEBUGF 1,"SOCKET_ring_write: ringbuff=%x ptr=%x size=%u\n", eax, esi, ecx |
489 | 1462 | ||
490 | mov bl, TH_SYN |
1463 | ; lock mutex |
491 | xor ecx, ecx |
1464 | pusha |
- | 1465 | lea ecx, [eax + RING_BUFFER.mutex] |
|
- | 1466 | call mutex_lock ; TODO: check what registers this function actually destroys |
|
- | 1467 | popa |
|
492 | stdcall build_tcp_packet, [sockAddr] |
1468 | |
493 | 1469 | ; calculate available size |
|
- | 1470 | mov edi, SOCKET_MAXDATA |
|
494 | mov eax, NET1OUT_QUEUE |
1471 | sub edi, [eax + RING_BUFFER.size] ; available buffer size in edi |
- | 1472 | cmp ecx, edi |
|
- | 1473 | jbe .copy |
|
Line 495... | Line -... | ||
495 | mov edx, [stack_ip] |
- | |
496 | mov ecx, [sockAddr] |
- | |
497 | cmp edx, [ecx + SOCKET.RemoteIP] |
1474 | mov ecx, edi |
- | 1475 | .copy: |
|
- | 1476 | mov edi, [eax + RING_BUFFER.write_ptr] |
|
- | 1477 | DEBUGF 2,"SOCKET_ring_write: %u bytes from %x to %x\n", ecx, esi, edi |
|
Line 498... | Line 1478... | ||
498 | jne .not_local |
1478 | |
499 | mov eax, IPIN_QUEUE |
1479 | ; update write ptr |
Line 500... | Line -... | ||
500 | - | ||
501 | .not_local: |
- | |
502 | ; Send it. |
- | |
503 | pop ebx |
1480 | push edi |
504 | call queue |
1481 | add edi, ecx |
505 | - | ||
506 | mov esi, [sockAddr] |
- | |
507 | 1482 | cmp edi, [eax + RING_BUFFER.end_ptr] |
|
Line 508... | Line 1483... | ||
508 | ; increment SND.NXT in socket |
1483 | jb @f |
509 | add esi, SOCKET.SND_NXT |
1484 | sub edi, SOCKET_MAXDATA ; WRAP |
510 | call inc_inet_esi |
1485 | @@: |
511 | 1486 | mov [eax + RING_BUFFER.write_ptr], edi |
|
512 | .exit: |
- | |
Line -... | Line 1487... | ||
- | 1487 | pop edi |
|
- | 1488 | ||
- | 1489 | ; update size |
|
- | 1490 | add [eax + RING_BUFFER.size], ecx |
|
- | 1491 | ||
- | 1492 | ; copy the data |
|
- | 1493 | push ecx |
|
- | 1494 | shr ecx, 1 |
|
- | 1495 | jnc .nb |
|
- | 1496 | movsb |
|
- | 1497 | .nb: |
|
- | 1498 | shr ecx, 1 |
|
- | 1499 | jnc .nw |
|
- | 1500 | movsw |
|
- | 1501 | .nw: |
|
- | 1502 | test ecx, ecx |
|
- | 1503 | jz .nd |
|
- | 1504 | rep movsd |
|
- | 1505 | .nd: |
|
- | 1506 | pop ecx |
|
- | 1507 | ||
513 | ; Get the socket number back, so we can return it |
1508 | ; unlock mutex |
- | 1509 | push eax ecx |
|
- | 1510 | lea ecx, [eax + RING_BUFFER.mutex] |
|
- | 1511 | call mutex_unlock ; TODO: check what registers this function actually destroys |
|
514 | stdcall net_socket_addr_to_num, [sockAddr] |
1512 | pop ecx eax |
Line 515... | Line 1513... | ||
515 | ret |
1513 | |
516 | 1514 | ret |
|
517 | .error.free: |
1515 | |
Line -... | Line 1516... | ||
- | 1516 | ;----------------------------------------------------------------- |
|
518 | stdcall net_socket_free, eax |
1517 | ; |
519 | 1518 | ; SOCKET_ring_read |
|
Line 520... | Line -... | ||
520 | .error: |
- | |
521 | DEBUGF 1, "K : socket_open_tcp (fail)\n" |
- | |
522 | or eax, -1 |
- | |
523 | ret |
- | |
524 | endp |
- | |
525 | - | ||
526 | ;; [53.1] Close DGRAM socket |
- | |
527 | ; |
- | |
528 | ; @param EBX is socket number |
- | |
529 | ; @return 0 (closed successfully) or -1 (error) in EAX |
- | |
530 | ;; |
- | |
531 | proc socket_close stdcall |
- | |
Line -... | Line 1519... | ||
- | 1519 | ; |
|
- | 1520 | ; IN: eax = ring struct ptr |
|
- | 1521 | ; ecx = bytes to read |
|
- | 1522 | ; edx = offset |
|
- | 1523 | ; edi = ptr to buffer start |
|
- | 1524 | ; |
|
- | 1525 | ; OUT: eax = unchanged |
|
532 | DEBUGF 1, "K : socket_close (0x%x)\n", ebx |
1526 | ; ecx = number of bytes read (0 on error) |
- | 1527 | ; edx = destroyed |
|
- | 1528 | ; esi = destroyed |
|
- | 1529 | ; edi = ptr to buffer end |
|
- | 1530 | ; |
|
- | 1531 | ;----------------------------------------------------------------- |
|
- | 1532 | align 4 |
|
Line 533... | Line -... | ||
533 | stdcall net_socket_num_to_addr, ebx |
- | |
534 | or eax, eax |
- | |
535 | jz .error |
- | |
536 | 1533 | SOCKET_ring_read: |
|
Line 537... | Line 1534... | ||
537 | stdcall net_socket_free, eax |
1534 | |
538 | - | ||
539 | xor eax, eax |
- | |
540 | ret |
- | |
541 | - | ||
542 | .error: |
- | |
543 | DEBUGF 1, "K : socket_close (fail)\n" |
1535 | DEBUGF 1,"SOCKET_ring_read: ringbuff=%x ptr=%x size=%u offset=%x\n", eax, edi, ecx, edx |
544 | or eax, -1 |
- | |
545 | ret |
- | |
546 | endp |
- | |
547 | - | ||
548 | ;; [53.8] Close STREAM socket |
- | |
549 | ; Closing TCP sockets takes time, so when you get successful return code |
- | |
550 | ; from this function doesn't always mean that socket is actually closed. |
1536 | |
551 | ; |
- | |
552 | ; @param EBX is socket number |
1537 | pusha |
553 | ; @return 0 (closed successfully) or -1 (error) in EAX |
- | |
554 | ;; |
- | |
555 | proc socket_close_tcp stdcall |
- | |
556 | local sockAddr dd ? |
- | |
557 | - | ||
558 | DEBUGF 1, "K : socket_close_tcp (0x%x)\n", ebx |
- | |
559 | ; first, remove any resend entries |
- | |
560 | pusha |
- | |
561 | - | ||
562 | mov esi, resendQ |
- | |
563 | mov ecx, 0 |
- | |
564 | - | ||
Line 565... | Line -... | ||
565 | .next_resendq: |
- | |
566 | cmp ecx, NUMRESENDENTRIES |
- | |
567 | je .last_resendq ; None left |
1538 | lea ecx, [eax + RING_BUFFER.mutex] |
568 | cmp [esi + 4], ebx |
1539 | call mutex_lock ; TODO: check what registers this function actually destroys |
569 | je @f ; found one |
1540 | popa |
Line -... | Line 1541... | ||
- | 1541 | ||
- | 1542 | mov esi, [eax + RING_BUFFER.read_ptr] |
|
- | 1543 | add esi, edx ; esi = start_ptr + offset |
|
- | 1544 | ||
570 | inc ecx |
1545 | neg edx |
Line 571... | Line 1546... | ||
571 | add esi, 8 |
1546 | add edx, [eax + RING_BUFFER.size] ; edx = snd.size - offset |
- | 1547 | jle .no_data_at_all |
|
572 | jmp .next_resendq |
1548 | |
- | 1549 | pusha |
|
Line 573... | Line -... | ||
573 | - | ||
574 | @@: |
- | |
575 | mov dword[esi + 4], 0 |
1550 | lea ecx, [eax + RING_BUFFER.mutex] |
Line -... | Line 1551... | ||
- | 1551 | call mutex_unlock ; TODO: check what registers this function actually destroys |
|
- | 1552 | popa |
|
- | 1553 | ||
- | 1554 | cmp ecx, edx |
|
576 | inc ecx |
1555 | ja .less_data |
577 | add esi, 8 |
1556 | |
- | 1557 | .copy: |
|
- | 1558 | DEBUGF 2,"SOCKET_ring_read: %u bytes from %x to %x\n", ecx, esi, edi |
|
- | 1559 | push ecx |
|
578 | jmp .next_resendq |
1560 | shr ecx, 1 |
579 | 1561 | jnc .nb |
|
580 | .last_resendq: |
- | |
Line -... | Line 1562... | ||
- | 1562 | movsb |
|
581 | popa |
1563 | .nb: |
582 | 1564 | shr ecx, 1 |
|
583 | stdcall net_socket_num_to_addr, ebx |
1565 | jnc .nw |
- | 1566 | movsw |
|
584 | or eax, eax |
1567 | .nw: |
585 | jz .error |
1568 | test ecx, ecx |
586 | 1569 | jz .nd |
|
587 | mov ebx, eax |
1570 | rep movsd |
- | 1571 | .nd: |
|
588 | mov [sockAddr], eax |
1572 | pop ecx |
589 | 1573 | ret |
|
590 | cmp [ebx + SOCKET.TCBState], TCB_LISTEN |
1574 | |
Line -... | Line 1575... | ||
- | 1575 | .no_data_at_all: |
|
- | 1576 | pusha |
|
- | 1577 | lea ecx, [eax + RING_BUFFER.mutex] |
|
- | 1578 | call mutex_unlock ; TODO: check what registers this function actually destroys |
|
- | 1579 | popa |
|
- | 1580 | ||
- | 1581 | DEBUGF 1,"SOCKET_ring_read: no data at all!\n" |
|
- | 1582 | xor ecx, ecx |
|
- | 1583 | ret |
|
- | 1584 | ||
- | 1585 | .less_data: |
|
- | 1586 | mov ecx, edx |
|
- | 1587 | jmp .copy |
|
- | 1588 | ||
- | 1589 | ||
- | 1590 | ;----------------------------------------------------------------- |
|
591 | je .destroy_tcb |
1591 | ; |
- | 1592 | ; SOCKET_ring_free |
|
- | 1593 | ; |
|
- | 1594 | ; Free's some bytes from the ringbuffer |
|
592 | cmp [ebx + SOCKET.TCBState], TCB_SYN_SENT |
1595 | ; |
- | 1596 | ; IN: eax = ptr to ring struct |
|
- | 1597 | ; ecx = data size |
|
Line 593... | Line -... | ||
593 | je .destroy_tcb |
- | |
594 | cmp [ebx + SOCKET.TCBState], TCB_CLOSED |
- | |
595 | je .destroy_tcb |
1598 | ; |
596 | - | ||
Line -... | Line 1599... | ||
- | 1599 | ; OUT: ecx = number of bytes free-ed |
|
597 | ; Now construct the response, and queue for sending by IP |
1600 | ; |
598 | mov eax, EMPTY_QUEUE |
1601 | ;----------------------------------------------------------------- |
599 | call dequeue |
1602 | align 4 |
- | 1603 | SOCKET_ring_free: |
|
600 | cmp ax, NO_BUFFER |
1604 | |
601 | je .error |
1605 | DEBUGF 1,"SOCKET_ring_free: %u bytes from ring %x\n", ecx, eax |
602 | 1606 | ||
603 | push eax |
1607 | push eax ecx |
- | 1608 | lea ecx, [eax + RING_BUFFER.mutex] |
|
604 | 1609 | call mutex_lock ; TODO: check what registers this function actually destroys |
|
605 | mov bl, TH_FIN+TH_ACK |
1610 | pop ecx eax |
606 | xor ecx, ecx |
1611 | |
Line 607... | Line 1612... | ||
607 | xor esi, esi |
1612 | sub [eax + RING_BUFFER.size], ecx |
608 | stdcall build_tcp_packet, [sockAddr] |
- | |
Line 609... | Line -... | ||
609 | - | ||
610 | mov ebx, [sockAddr] |
1613 | jb .error |
611 | ; increament SND.NXT in socket |
1614 | add [eax + RING_BUFFER.read_ptr], ecx |
612 | lea esi, [ebx + SOCKET.SND_NXT] |
- | |
Line 613... | Line -... | ||
613 | call inc_inet_esi |
- | |
614 | - | ||
615 | ; Get the socket state |
- | |
616 | mov eax, [ebx + SOCKET.TCBState] |
1615 | |
617 | cmp eax, TCB_SYN_RECEIVED |
- | |
618 | je .fin_wait_1 |
1616 | mov edx, [eax + RING_BUFFER.end_ptr] |
619 | cmp eax, TCB_ESTABLISHED |
- | |
620 | je .fin_wait_1 |
- | |
621 | 1617 | cmp [eax + RING_BUFFER.read_ptr], edx |
|
622 | ; assume CLOSE WAIT |
- | |
623 | ; Send a fin, then enter last-ack state |
- | |
624 | mov [ebx + SOCKET.TCBState], TCB_LAST_ACK |
1618 | jb @f |
625 | jmp .send |
- | |
626 | 1619 | sub [eax + RING_BUFFER.read_ptr], SOCKET_MAXDATA |
|
Line 627... | Line 1620... | ||
627 | .fin_wait_1: |
1620 | @@: |
- | 1621 | ||
628 | ; Send a fin, then enter finwait2 state |
1622 | push eax ecx |
629 | mov [ebx + SOCKET.TCBState], TCB_FIN_WAIT_1 |
1623 | lea ecx, [eax + RING_BUFFER.mutex] ; TODO: check what registers this function actually destroys |
Line 630... | Line 1624... | ||
630 | 1624 | call mutex_unlock |
|
631 | .send: |
1625 | pop ecx eax |
632 | mov eax, NET1OUT_QUEUE |
1626 | |
- | 1627 | ret |
|
- | 1628 | ||
- | 1629 | .error: ; we could free all available bytes, but that would be stupid, i guess.. |
|
- | 1630 | DEBUGF 1,"SOCKET_ring_free: buffer=%x error!\n", eax |
|
- | 1631 | add [eax + RING_BUFFER.size], ecx |
|
- | 1632 | ||
- | 1633 | push eax |
|
- | 1634 | lea ecx, [eax + RING_BUFFER.mutex] |
|
- | 1635 | call mutex_unlock ; TODO: check what registers this function actually destroys |
|
- | 1636 | pop eax |
|
- | 1637 | ||
- | 1638 | xor ecx, ecx |
|
- | 1639 | ret |
|
- | 1640 | ||
- | 1641 | ||
- | 1642 | ;----------------------------------------------------------------- |
|
- | 1643 | ; |
|
- | 1644 | ; SOCKET_block |
|
- | 1645 | ; |
|
- | 1646 | ; Suspends the thread attached to a socket |
|
- | 1647 | ; |
|
- | 1648 | ; IN: eax = socket ptr |
|
- | 1649 | ; OUT: / |
|
- | 1650 | ; |
|
- | 1651 | ;----------------------------------------------------------------- |
|
Line 633... | Line 1652... | ||
633 | mov edx, [stack_ip] |
1652 | align 4 |
634 | mov ecx, [sockAddr] |
1653 | SOCKET_block: |
635 | cmp edx, [ecx + SOCKET.RemoteIP] |
1654 | |
636 | jne .not_local |
1655 | DEBUGF 1,"SOCKET_block: %x\n", eax |
637 | mov eax, IPIN_QUEUE |
- | |
638 | 1656 | ||
639 | .not_local: |
1657 | pushf |
640 | ; Send it. |
1658 | cli |
641 | pop ebx |
1659 | |
- | 1660 | ; Set the 'socket is blocked' flag |
|
642 | call queue |
1661 | or [eax + SOCKET.state], SS_BLOCKED |
643 | jmp .exit |
1662 | |
644 | 1663 | ; Suspend the thread |
|
645 | .destroy_tcb: |
1664 | push edx |
646 | 1665 | mov edx, [TASK_BASE] |
|
647 | ; Clear the socket variables |
1666 | mov [edx + TASKDATA.state], 1 ; Suspended |
- | 1667 | ||
Line 648... | Line 1668... | ||
648 | stdcall net_socket_free, ebx |
1668 | ; Remember the thread ID so we can wake it up again |
649 | 1669 | mov edx, [edx + TASKDATA.pid] |
|
650 | .exit: |
1670 | DEBUGF 1,"SOCKET_block: suspending thread: %u\n", edx |
- | 1671 | mov [eax + SOCKET.TID], edx |
|
- | 1672 | pop edx |
|
651 | xor eax, eax |
1673 | |
652 | ret |
- | |
Line 653... | Line -... | ||
653 | - | ||
654 | .error: |
- | |
655 | DEBUGF 1, "K : socket_close_tcp (fail)\n" |
- | |
656 | or eax, -1 |
1674 | call change_task |
657 | ret |
- | |
658 | endp |
- | |
659 | 1675 | popf |
|
660 | ;; [53.2] Poll socket |
- | |
Line -... | Line 1676... | ||
- | 1676 | ||
661 | ; |
1677 | DEBUGF 1,"SOCKET_block: continueing\n" |
- | 1678 | ||
- | 1679 | ret |
|
- | 1680 | ||
662 | ; @param EBX is socket number |
1681 | |
663 | ; @return count or bytes in rx buffer or 0 (error) in EAX |
- | |
664 | ;; |
1682 | ;----------------------------------------------------------------- |
665 | proc socket_poll stdcall |
1683 | ; |
666 | ; DEBUGF 1, "socket_poll(0x%x)\n", ebx |
1684 | ; SOCKET_notify |
- | 1685 | ; |
|
- | 1686 | ; notify's the owner of a socket that something happened |
|
667 | stdcall net_socket_num_to_addr, ebx |
1687 | ; |
668 | or eax, eax |
1688 | ; IN: eax = socket ptr |
- | 1689 | ; OUT: / |
|
669 | jz .error |
1690 | ; |
- | 1691 | ;----------------------------------------------------------------- |
|
- | 1692 | align 4 |
|
- | 1693 | SOCKET_notify: |
|
670 | 1694 | ||
671 | mov eax, [eax + SOCKET.rxDataCount] |
1695 | DEBUGF 1,"SOCKET_notify: %x\n", eax |
672 | ret |
1696 | |
673 | 1697 | call SOCKET_check |
|
674 | .error: |
- | |
675 | xor eax, eax |
1698 | jz .error |
676 | ret |
1699 | |
Line -... | Line 1700... | ||
- | 1700 | test [eax + SOCKET.state], SS_BLOCKED |
|
- | 1701 | jnz .unblock |
|
677 | endp |
1702 | |
- | 1703 | test [eax + SOCKET.options], SO_NONBLOCK |
|
- | 1704 | jz .error |
|
- | 1705 | ||
- | 1706 | push eax ecx esi |
|
- | 1707 | ||
- | 1708 | ; socket exists and is of non blocking type. |
|
- | 1709 | ; We'll try to flag an event to the thread |
|
- | 1710 | ||
- | 1711 | mov eax, [eax + SOCKET.TID] |
|
- | 1712 | test eax, eax |
|
- | 1713 | jz .done |
|
- | 1714 | mov ecx, 1 |
|
- | 1715 | mov esi, TASK_DATA + TASKDATA.pid |
|
- | 1716 | ||
- | 1717 | .next_pid: |
|
- | 1718 | cmp [esi], eax |
|
- | 1719 | je .found_pid |
|
- | 1720 | inc ecx |
|
- | 1721 | add esi, 0x20 |
|
- | 1722 | cmp ecx, [TASK_COUNT] |
|
- | 1723 | jbe .next_pid |
|
Line -... | Line 1724... | ||
- | 1724 | ; PID not found, TODO: close socket! |
|
678 | 1725 | jmp .done |
|
- | 1726 | ||
- | 1727 | .found_pid: |
|
- | 1728 | shl ecx, 8 |
|
- | 1729 | or [ecx + SLOT_BASE + APPDATA.event_mask], EVENT_NETWORK |
|
- | 1730 | ||
- | 1731 | DEBUGF 1,"SOCKET_notify: Raised a network event!\n" |
|
- | 1732 | ||
- | 1733 | jmp .done |
|
- | 1734 | ||
- | 1735 | .unblock: |
|
- | 1736 | push eax ecx esi |
|
- | 1737 | ; Clear the 'socket is blocked' flag |
|
- | 1738 | and [eax + SOCKET.state], not SS_BLOCKED |
|
- | 1739 | ||
- | 1740 | ; Find the thread's TASK_DATA |
|
679 | ;; [53.6] Get socket TCB state |
1741 | mov eax, [eax + SOCKET.TID] |
680 | ; |
1742 | test eax, eax |
681 | ; @param EBX is socket number |
1743 | jz .error |
Line 682... | Line 1744... | ||
682 | ; @return socket TCB state or 0 (error) in EAX |
1744 | xor ecx, ecx |
683 | ;; |
- | |
684 | proc socket_status stdcall |
- | |
685 | ;; DEBUGF 1, "socket_status(0x%x)\n", ebx |
- | |
686 | stdcall net_socket_num_to_addr, ebx |
- | |
687 | or eax, eax |
- | |
688 | jz .error |
- | |
689 | 1745 | inc ecx |
|
Line 690... | Line -... | ||
690 | mov eax, [eax + SOCKET.TCBState] |
- | |
691 | ret |
1746 | mov esi, TASK_DATA |
692 | 1747 | .next: |
|
693 | .error: |
- | |
694 | xor eax, eax |
- | |
Line 695... | Line -... | ||
695 | ret |
- | |
696 | endp |
- | |
697 | - | ||
698 | ;; [53.3] Get one byte from rx buffer |
- | |
699 | ; This function can return 0 in two cases: if there's one byte read and |
- | |
700 | ; non left, and if an error occured. Behavior should be changed and function |
- | |
701 | ; shouldn't be used for now. Consider using [53.11] instead. |
- | |
702 | ; |
- | |
703 | ; @param EBX is socket number |
- | |
704 | ; @return number of bytes left in rx buffer or 0 (error) in EAX |
1748 | cmp [esi + TASKDATA.pid], eax |
705 | ; @return byte read in BL |
1749 | je .found |
706 | ;; |
- | |
Line 707... | Line 1750... | ||
707 | proc socket_read stdcall |
1750 | inc ecx |
708 | ; DEBUGF 1, "socket_read(0x%x)\n", ebx |
1751 | add esi, 0x20 |
709 | stdcall net_socket_num_to_addr, ebx |
- | |
710 | or eax, eax |
1752 | cmp ecx, [TASK_COUNT] |
711 | jz .error |
1753 | jbe .next |
712 | - | ||
Line 713... | Line -... | ||
713 | mov ebx, eax |
- | |
714 | lea ecx, [eax + SOCKET.mutex] |
1754 | jmp .error |
715 | call mutex_lock |
- | |
Line 716... | Line -... | ||
716 | - | ||
717 | mov eax, [ebx + SOCKET.rxDataCount] ; get count of bytes |
1755 | .found: |
718 | test eax, eax |
- | |
719 | jz .error_release |
- | |
720 | 1756 | ||
721 | dec eax |
- | |
722 | mov esi, ebx ; esi is address of socket |
1757 | ; Run the thread |
- | 1758 | mov [esi + TASKDATA.state], 0 ; Running |
|
- | 1759 | DEBUGF 1,"SOCKET_notify: Unblocked socket!\n" |
|
- | 1760 | ||
- | 1761 | .done: |
|
- | 1762 | pop esi ecx eax |
|
- | 1763 | ||
723 | mov [ebx + SOCKET.rxDataCount], eax ; store new count |
1764 | .error: |
- | 1765 | ret |
|
724 | movzx eax, byte[ebx + SOCKET.rxData] ; get the byte |
1766 | |
Line 725... | Line 1767... | ||
725 | 1767 | ||
726 | mov ecx, SOCKETBUFFSIZE - SOCKET.rxData - 1 |
- | |
727 | lea edi, [esi + SOCKET.rxData] |
- | |
728 | lea esi, [edi + 1] |
- | |
729 | cld |
- | |
730 | push ecx |
- | |
731 | shr ecx, 2 |
1768 | ;-------------------------------------------------------------------- |
732 | rep movsd |
- | |
733 | pop ecx |
- | |
734 | and ecx, 3 |
- | |
735 | rep movsb |
- | |
736 | - | ||
737 | lea ecx, [ebx + SOCKET.mutex] |
- | |
738 | mov ebx, eax |
1769 | ; |
- | 1770 | ; SOCKET_alloc |
|
739 | call mutex_unlock |
1771 | ; |
740 | mov eax, ebx |
1772 | ; Allocate memory for socket data and put new socket into the list |
741 | ret |
1773 | ; Newly created socket is initialized with calling PID and number and |
742 | 1774 | ; put into beginning of list (which is a fastest way). |
|
743 | .error_release: |
- | |
744 | lea ecx, [ebx + SOCKET.mutex] |
1775 | ; |
745 | call mutex_unlock |
- | |
746 | .error: |
1776 | ; IN: / |
- | 1777 | ; OUT: eax = 0 on error, socket ptr otherwise |
|
- | 1778 | ; edi = socket number |
|
747 | xor ebx, ebx |
1779 | ; ZF = cleared on error |
- | 1780 | ; |
|
748 | xor eax, eax |
1781 | ;-------------------------------------------------------------------- |
749 | ret |
- | |
- | 1782 | align 4 |
|
750 | endp |
1783 | SOCKET_alloc: |
751 | 1784 | ||
Line -... | Line 1785... | ||
- | 1785 | push ebx |
|
- | 1786 | ||
- | 1787 | stdcall kernel_alloc, SOCKETBUFFSIZE |
|
- | 1788 | DEBUGF 1, "SOCKET_alloc: ptr=%x\n", eax |
|
- | 1789 | or eax, eax |
|
- | 1790 | jz .exit |
|
- | 1791 | ||
- | 1792 | ; zero-initialize allocated memory |
|
- | 1793 | push eax |
|
- | 1794 | mov edi, eax |
|
- | 1795 | mov ecx, SOCKETBUFFSIZE / 4 |
|
- | 1796 | xor eax, eax |
|
- | 1797 | rep stosd |
|
752 | ;; [53.11] Get specified number of bytes from rx buffer |
1798 | pop eax |
- | 1799 | ||
- | 1800 | ; set send-and receive procedures to return -1 |
|
- | 1801 | mov [eax + SOCKET.snd_proc], s_error |
|
- | 1802 | mov [eax + SOCKET.rcv_proc], s_error |
|
Line 753... | Line 1803... | ||
753 | ; Number of bytes in rx buffer can be less than requested size. In this case, |
1803 | |
754 | ; only available number of bytes is read. |
- | |
755 | ; This function can return 0 in two cases: if there's no data to read, and if |
1804 | ; find first free socket number and use it |
756 | ; an error occured. Behavior should be changed. |
1805 | mov edi, [last_socket_num] |
Line 757... | Line 1806... | ||
757 | ; |
1806 | .next_socket_number: |
758 | ; @param EBX is socket number |
- | |
Line 759... | Line 1807... | ||
759 | ; @param ECX is pointer to application buffer |
1807 | inc edi |
760 | ; @param EDX is application buffer size (number of bytes to read) |
1808 | jz .next_socket_number ; avoid socket nr 0 |
- | 1809 | cmp edi, -1 |
|
761 | ; @return number of bytes read or 0 (error) in EAX |
1810 | je .next_socket_number ; avoid socket nr -1 |
Line 762... | Line -... | ||
762 | ;; |
- | |
763 | proc socket_read_packet stdcall |
1811 | mov ebx, net_sockets |
764 | ; DEBUGF 1, "socket_read_packet(0x%x)\n", ebx |
1812 | .next_socket: |
765 | stdcall net_socket_num_to_addr, ebx ; get real socket address |
1813 | mov ebx, [ebx + SOCKET.NextPtr] |
- | 1814 | test ebx, ebx |
|
Line -... | Line 1815... | ||
- | 1815 | jz .last_socket |
|
766 | or eax, eax |
1816 | |
Line 767... | Line 1817... | ||
767 | jz .error |
1817 | cmp [ebx + SOCKET.Number], edi |
Line 768... | Line -... | ||
768 | - | ||
769 | mov ebx, eax |
1818 | jne .next_socket |
770 | - | ||
771 | push ecx edx |
1819 | jmp .next_socket_number |
772 | lea ecx, [eax + SOCKET.mutex] |
- | |
Line -... | Line 1820... | ||
- | 1820 | ||
- | 1821 | .last_socket: |
|
- | 1822 | mov [last_socket_num], edi |
|
- | 1823 | mov [eax + SOCKET.Number], edi |
|
- | 1824 | DEBUGF 1, "SOCKET_alloc: number=%u\n", edi |
|
- | 1825 | ||
773 | call mutex_lock |
1826 | ; Fill in PID |
774 | pop edx ecx |
1827 | mov ebx, [TASK_BASE] |
- | 1828 | mov ebx, [ebx + TASKDATA.pid] |
|
- | 1829 | mov [eax + SOCKET.PID], ebx |
|
- | 1830 | mov [eax + SOCKET.TID], ebx ; currently TID = PID in kolibrios :( |
|
- | 1831 | ||
Line 775... | Line -... | ||
775 | - | ||
776 | mov eax, [ebx + SOCKET.rxDataCount] ; get count of bytes |
1832 | ; init mutex |
Line 777... | Line -... | ||
777 | test eax, eax ; if count of bytes is zero.. |
- | |
778 | jz .exit ; exit function (eax will be zero) |
- | |
779 | - | ||
780 | test edx, edx ; if buffer size is zero, copy all data |
- | |
781 | jz .copy_all_bytes |
- | |
782 | cmp edx, eax ; if buffer size is larger then the bytes of data, copy all data |
- | |
783 | jge .copy_all_bytes |
- | |
784 | - | ||
785 | sub eax, edx ; store new count (data bytes in buffer - bytes we're about to copy) |
- | |
786 | mov [ebx + SOCKET.rxDataCount], eax ; |
1833 | pusha |
787 | push eax |
1834 | lea ecx, [eax + SOCKET.mutex] |
788 | mov eax, edx ; number of bytes we want to copy must be in eax |
- | |
789 | call .start_copy ; copy to the application |
- | |
790 | 1835 | call mutex_init |
|
791 | mov esi, ebx ; now we're going to copy the remaining bytes to the beginning |
1836 | popa |
Line -... | Line 1837... | ||
- | 1837 | ||
- | 1838 | ; add socket to the list by re-arranging some pointers |
|
792 | add esi, SOCKET.rxData ; we dont need to copy the header |
1839 | mov ebx, [net_sockets + SOCKET.NextPtr] |
- | 1840 | ||
793 | mov edi, esi ; edi is where we're going to copy to |
1841 | mov [eax + SOCKET.PrevPtr], net_sockets |
Line 794... | Line -... | ||
794 | add esi, edx ; esi is from where we copy |
- | |
795 | pop ecx ; count of bytes we have left |
1842 | mov [eax + SOCKET.NextPtr], ebx |
- | 1843 | ||
- | 1844 | test ebx, ebx |
|
- | 1845 | jz @f |
|
Line -... | Line 1846... | ||
- | 1846 | ||
- | 1847 | pusha |
|
- | 1848 | lea ecx, [ebx + SOCKET.mutex] |
|
796 | push ecx ; push it again so we can re-use it later |
1849 | call mutex_lock |
- | 1850 | popa |
|
797 | shr ecx, 2 ; divide eax by 4 |
1851 | |
- | 1852 | mov [ebx + SOCKET.PrevPtr], eax |
|
798 | cld |
1853 | |
- | 1854 | pusha |
|
- | 1855 | lea ecx, [ebx + SOCKET.mutex] |
|
Line -... | Line 1856... | ||
- | 1856 | call mutex_unlock |
|
- | 1857 | popa |
|
- | 1858 | @@: |
|
799 | rep movsd ; copy all full dwords |
1859 | |
800 | pop ecx |
1860 | mov [net_sockets + SOCKET.NextPtr], eax |
801 | and ecx, 3 |
1861 | or eax, eax ; used to clear zero flag |
Line 802... | Line -... | ||
802 | rep movsb ; copy remaining bytes |
- | |
803 | - | ||
804 | .exit: |
- | |
805 | lea ecx, [ebx + SOCKET.mutex] |
- | |
806 | mov ebx, eax |
- | |
807 | call mutex_unlock |
- | |
808 | mov eax, ebx |
- | |
809 | ret ; at last, exit |
- | |
810 | - | ||
Line 811... | Line 1862... | ||
811 | .error: |
1862 | .exit: |
- | 1863 | pop ebx |
|
812 | xor eax, eax |
1864 | |
813 | ret |
1865 | ret |
814 | 1866 | ||
815 | .copy_all_bytes: |
1867 | |
816 | xor esi, esi |
1868 | ;---------------------------------------------------- |
817 | mov [ebx + SOCKET.rxDataCount], esi ; store new count (zero) |
- | |
818 | call .start_copy |
1869 | ; |
819 | lea ecx, [ebx + SOCKET.mutex] |
- | |
820 | mov ebx, eax |
1870 | ; SOCKET_free |
- | 1871 | ; |
|
821 | call mutex_unlock |
1872 | ; Free socket data memory and remove socket from the list |
822 | mov eax, ebx |
- | |
823 | ret |
- | |
824 | 1873 | ; |
|
825 | .start_copy: |
- | |
826 | mov edi, ecx |
1874 | ; IN: eax = socket ptr |
827 | mov esi, ebx |
- | |
Line 828... | Line -... | ||
828 | add esi, SOCKET.rxData ; we dont need to copy the header |
- | |
829 | mov ecx, eax ; eax is count of bytes |
- | |
830 | push ecx |
- | |
831 | shr ecx, 2 ; divide eax by 4 |
- | |
832 | cld ; copy all full dwords |
- | |
833 | rep movsd |
- | |
834 | pop ecx |
- | |
835 | and ecx, 3 |
1875 | ; OUT: / |
Line 836... | Line 1876... | ||
836 | rep movsb ; copy the rest bytes |
1876 | ; |
Line -... | Line 1877... | ||
- | 1877 | ;---------------------------------------------------- |
|
837 | retn ; exit, or go back to shift remaining bytes if any |
1878 | align 4 |
- | 1879 | SOCKET_free: |
|
- | 1880 | ||
- | 1881 | DEBUGF 1, "SOCKET_free: %x\n", eax |
|
838 | endp |
1882 | |
Line 839... | Line -... | ||
839 | - | ||
840 | ;; [53.4] Send data through DGRAM socket |
- | |
841 | ; |
1883 | call SOCKET_check |
842 | ; @param EBX is socket number |
- | |
843 | ; @param ECX is application data size (number of bytes to send) |
- | |
Line 844... | Line -... | ||
844 | ; @param EDX is pointer to application data buffer |
- | |
845 | ; @return 0 (sent successfully) or -1 (error) in EAX |
1884 | jz .error |
846 | ;; |
1885 | |
Line 847... | Line 1886... | ||
847 | proc socket_write stdcall |
1886 | push ebx |
848 | ; DEBUGF 1, "socket_write(0x%x)\n", ebx |
- | |
849 | stdcall net_socket_num_to_addr, ebx ; get real socket address |
1887 | |
850 | or eax, eax |
1888 | pusha |
851 | jz .error |
- | |
Line 852... | Line -... | ||
852 | - | ||
853 | mov ebx, eax |
- | |
Line -... | Line 1889... | ||
- | 1889 | lea ecx, [eax + SOCKET.mutex] |
|
- | 1890 | call mutex_lock |
|
- | 1891 | popa |
|
- | 1892 | ||
- | 1893 | cmp [eax + SOCKET.Domain], AF_INET4 |
|
- | 1894 | jnz .no_tcp |
|
- | 1895 | ||
- | 1896 | cmp [eax + SOCKET.Protocol], IP_PROTO_TCP |
|
854 | 1897 | jnz .no_tcp |
|
- | 1898 | ||
- | 1899 | mov ebx, eax |
|
- | 1900 | stdcall kernel_free, [ebx + STREAM_SOCKET.rcv.start_ptr] |
|
- | 1901 | stdcall kernel_free, [ebx + STREAM_SOCKET.snd.start_ptr] |
|
Line 855... | Line -... | ||
855 | mov eax, EMPTY_QUEUE |
- | |
856 | call dequeue |
1902 | mov eax, ebx |
857 | cmp ax, NO_BUFFER |
- | |
858 | je .error |
- | |
859 | - | ||
860 | ; Save the queue entry number |
- | |
861 | push eax |
- | |
862 | - | ||
863 | ; save the pointers to the data buffer & size |
- | |
864 | push edx |
- | |
Line -... | Line 1903... | ||
- | 1903 | .no_tcp: |
|
865 | push ecx |
1904 | |
- | 1905 | push eax ; this will be passed to kernel_free |
|
- | 1906 | mov ebx, [eax + SOCKET.NextPtr] |
|
- | 1907 | mov eax, [eax + SOCKET.PrevPtr] |
|
- | 1908 | ||
866 | 1909 | DEBUGF 1, "SOCKET_free: linking socket %x to socket %x\n", eax, ebx |
|
Line 867... | Line 1910... | ||
867 | ; convert buffer pointer eax to the absolute address |
1910 | |
868 | mov ecx, IPBUFFSIZE |
1911 | test eax, eax |
869 | mul ecx |
1912 | jz @f |
870 | add eax, IPbuffs |
- | |
Line -... | Line 1913... | ||
- | 1913 | mov [eax + SOCKET.NextPtr], ebx |
|
871 | 1914 | @@: |
|
872 | mov edx, eax |
1915 | |
873 | 1916 | test ebx, ebx |
|
- | 1917 | jz @f |
|
874 | ; So, ebx holds the socket ptr, edx holds the IPbuffer ptr |
1918 | mov [ebx + SOCKET.PrevPtr], eax |
- | 1919 | @@: |
|
- | 1920 | ||
875 | 1921 | call kernel_free |
|
876 | ; Fill in the IP header (some data is in the socket descriptor) |
1922 | pop ebx |
877 | mov eax, [ebx + SOCKET.LocalIP] |
1923 | |
878 | mov [edx + IP_PACKET.SourceAddress], eax |
1924 | DEBUGF 1, "SOCKET_free: success!\n" |
- | 1925 | ||
879 | mov eax, [ebx + SOCKET.RemoteIP] |
1926 | .error: |
Line 880... | Line 1927... | ||
880 | mov [edx + IP_PACKET.DestinationAddress], eax |
1927 | ret |
881 | - | ||
882 | mov [edx + IP_PACKET.VersionAndIHL], 0x45 |
- | |
883 | mov [edx + IP_PACKET.TypeOfService], 0 |
- | |
Line 884... | Line 1928... | ||
884 | 1928 | ||
885 | pop eax ; Get the UDP data length |
1929 | ;------------------------------------ |
Line 886... | Line 1930... | ||
886 | push eax |
1930 | ; |
887 | 1931 | ; SOCKET_fork |
|
888 | add eax, 20 + 8 ; add IP header and UDP header lengths |
1932 | ; |
889 | xchg al, ah |
- | |
890 | mov [edx + IP_PACKET.TotalLength], ax |
- | |
891 | xor eax, eax |
1933 | ; Create a child socket |
892 | mov [edx + IP_PACKET.Identification], ax |
1934 | ; |
893 | mov [edx + IP_PACKET.FlagsAndFragmentOffset], 0x0040 |
1935 | ; IN: socket nr in ebx |
Line -... | Line 1936... | ||
- | 1936 | ; OUT: child socket nr in eax |
|
- | 1937 | ; |
|
- | 1938 | ;----------------------------------- |
|
894 | mov [edx + IP_PACKET.TimeToLive], 0x20 |
1939 | align 4 |
Line 895... | Line -... | ||
895 | mov [edx + IP_PACKET.Protocol], PROTOCOL_UDP |
- | |
896 | - | ||
897 | ; Checksum left unfilled |
- | |
898 | mov [edx + IP_PACKET.HeaderChecksum], ax |
- | |
899 | 1940 | SOCKET_fork: |
|
Line 900... | Line -... | ||
900 | ; Fill in the UDP header (some data is in the socket descriptor) |
- | |
901 | mov ax, [ebx + SOCKET.LocalPort] |
- | |
Line 902... | Line -... | ||
902 | mov [edx + 20 + UDP_PACKET.SourcePort], ax |
- | |
903 | - | ||
904 | mov ax, [ebx + SOCKET.RemotePort] |
- | |
905 | mov [edx + 20 + UDP_PACKET.DestinationPort], ax |
- | |
Line -... | Line 1941... | ||
- | 1941 | ||
- | 1942 | DEBUGF 1,"SOCKET_fork: %x\n", ebx |
|
- | 1943 | ||
- | 1944 | ; Exit if backlog queue is full |
|
906 | 1945 | mov eax, [ebx + SOCKET_QUEUE_LOCATION + queue.size] |
|
- | 1946 | cmp ax, [ebx + SOCKET.backlog] |
|
- | 1947 | jae .fail |
|
- | 1948 | ||
- | 1949 | ; Allocate new socket |
|
- | 1950 | push ebx |
|
- | 1951 | call SOCKET_alloc |
|
- | 1952 | pop ebx |
|
- | 1953 | jz .fail |
|
907 | pop eax |
1954 | |
Line -... | Line 1955... | ||
- | 1955 | push eax |
|
- | 1956 | mov esi, esp |
|
- | 1957 | add_to_queue (ebx + SOCKET_QUEUE_LOCATION), MAX_backlog, 4, .fail2 |
|
- | 1958 | pop eax |
|
908 | push eax |
1959 | |
909 | - | ||
Line 910... | Line -... | ||
910 | add eax, 8 |
- | |
911 | xchg al, ah |
- | |
912 | mov [edx + 20 + UDP_PACKET.Length], ax |
- | |
913 | - | ||
914 | ; Checksum left unfilled |
1960 | ; Copy structure from current socket to new |
915 | xor eax, eax |
- | |
Line 916... | Line -... | ||
916 | mov [edx + 20 + UDP_PACKET.Checksum], ax |
- | |
917 | - | ||
918 | pop ecx ; count of bytes to send |
- | |
Line 919... | Line -... | ||
919 | mov ebx, ecx ; need the length later |
- | |
Line 920... | Line -... | ||
920 | pop eax ; get callers ptr to data to send |
- | |
Line -... | Line 1961... | ||
- | 1961 | ; We start at PID to preserve the socket num, and the 2 pointers at beginning of socket |
|
- | 1962 | lea esi, [ebx + SOCKET.PID] |
|
- | 1963 | lea edi, [eax + SOCKET.PID] |
|
- | 1964 | mov ecx, (SOCKET_QUEUE_LOCATION - SOCKET.PID + 3)/4 |
|
- | 1965 | rep movsd |
|
- | 1966 | ||
- | 1967 | and [eax + SOCKET.options], not SO_ACCEPTCON |
|
- | 1968 | ||
- | 1969 | ret |
|
- | 1970 | ||
- | 1971 | .fail2: |
|
- | 1972 | add esp, 4+4+4 |
|
- | 1973 | .fail: |
|
- | 1974 | DEBUGF 1,"SOCKET_fork: failed\n" |
|
- | 1975 | xor eax, eax |
|
- | 1976 | ret |
|
- | 1977 | ||
- | 1978 | ||
921 | 1979 | ;--------------------------------------------------- |
|
- | 1980 | ; |
|
- | 1981 | ; SOCKET_num_to_ptr |
|
- | 1982 | ; |
|
- | 1983 | ; Get socket structure address by its number |
|
- | 1984 | ; |
|
- | 1985 | ; IN: ecx = socket number |
|
- | 1986 | ; OUT: eax = 0 on error, socket ptr otherwise |
|
922 | ; Get the address of the callers data |
1987 | ; ZF = set on error |
- | 1988 | ; |
|
- | 1989 | ;--------------------------------------------------- |
|
- | 1990 | align 4 |
|
- | 1991 | SOCKET_num_to_ptr: |
|
923 | mov edi, [TASK_BASE] |
1992 | |
- | 1993 | DEBUGF 1,"SOCKET_num_to_ptr: num=%u ", ecx |
|
- | 1994 | ||
- | 1995 | mov eax, net_sockets |
|
- | 1996 | ||
- | 1997 | .next_socket: |
|
924 | add edi, TASKDATA.mem_start |
1998 | mov eax, [eax + SOCKET.NextPtr] |
Line -... | Line 1999... | ||
- | 1999 | or eax, eax |
|
925 | add eax, [edi] |
2000 | jz .error |
Line 926... | Line -... | ||
926 | mov esi, eax |
- | |
927 | - | ||
928 | mov edi, edx |
- | |
929 | add edi, 28 |
- | |
930 | cld |
- | |
931 | rep movsb ; copy the data across |
- | |
932 | - | ||
933 | ; we have edx as IPbuffer ptr. |
- | |
934 | ; Fill in the UDP checksum |
- | |
935 | ; First, fill in pseudoheader |
- | |
936 | mov eax, [edx + IP_PACKET.SourceAddress] |
2001 | cmp [eax + SOCKET.Number], ecx |
937 | mov [pseudoHeader], eax |
- | |
938 | mov eax, [edx + IP_PACKET.DestinationAddress] |
- | |
Line 939... | Line -... | ||
939 | mov [pseudoHeader + 4], eax |
- | |
940 | mov word[pseudoHeader + 8], PROTOCOL_UDP shl 8 + 0 ; 0 + protocol |
- | |
Line 941... | Line -... | ||
941 | add ebx, 8 |
- | |
942 | mov eax, ebx |
- | |
943 | xchg al, ah |
- | |
944 | mov [pseudoHeader + 10], ax |
- | |
945 | - | ||
946 | mov eax, pseudoHeader |
- | |
947 | mov [checkAdd1], eax |
- | |
948 | mov [checkSize1], word 12 |
- | |
949 | mov eax, edx |
- | |
950 | add eax, 20 |
- | |
951 | mov [checkAdd2], eax |
- | |
952 | mov eax, ebx |
- | |
Line 953... | Line -... | ||
953 | mov [checkSize2], ax ; was eax!! mjh 8/7/02 |
- | |
954 | - | ||
955 | call checksum |
- | |
Line -... | Line 2002... | ||
- | 2002 | jne .next_socket |
|
956 | 2003 | ||
957 | ; store it in the UDP checksum ( in the correct order! ) |
2004 | test eax, eax |
- | 2005 | ||
958 | mov ax, [checkResult] |
2006 | DEBUGF 1,"ptr=%x\n", eax |
- | 2007 | ret |
|
- | 2008 | ||
- | 2009 | .error: |
|
Line 959... | Line -... | ||
959 | - | ||
960 | ; If the UDP checksum computes to 0, we must make it 0xffff |
- | |
961 | ; (0 is reserved for 'not used') |
- | |
962 | test ax, ax |
- | |
963 | jnz @f |
2010 | DEBUGF 1,"not found\n", eax |
964 | mov ax, 0xffff |
- | |
965 | 2011 | ret |
|
Line -... | Line 2012... | ||
- | 2012 | ||
- | 2013 | ||
- | 2014 | ;--------------------------------------------------- |
|
- | 2015 | ; |
|
- | 2016 | ; SOCKET_ptr_to_num |
|
966 | @@: |
2017 | ; |
- | 2018 | ; Get socket number by its address |
|
- | 2019 | ; |
|
- | 2020 | ; IN: eax = socket ptr |
|
- | 2021 | ; OUT: eax = 0 on error, socket num otherwise |
|
- | 2022 | ; ZF = set on error |
|
- | 2023 | ; |
|
- | 2024 | ;--------------------------------------------------- |
|
- | 2025 | align 4 |
|
- | 2026 | SOCKET_ptr_to_num: |
|
- | 2027 | ||
- | 2028 | DEBUGF 1,"SOCKET_ptr_to_num: ptr=%x ", eax |
|
- | 2029 | ||
- | 2030 | call SOCKET_check |
|
- | 2031 | jz .error |
|
- | 2032 | ||
- | 2033 | mov eax, [eax + SOCKET.Number] |
|
- | 2034 | ||
- | 2035 | DEBUGF 1,"num=%u\n", eax |
|
- | 2036 | ret |
|
- | 2037 | ||
- | 2038 | .error: |
|
- | 2039 | DEBUGF 1,"not found\n", eax |
|
- | 2040 | ret |
|
- | 2041 | ||
- | 2042 | ||
- | 2043 | ;--------------------------------------------------- |
|
- | 2044 | ; |
|
- | 2045 | ; SOCKET_check |
|
- | 2046 | ; |
|
- | 2047 | ; checks if the given value is really a socket ptr |
|
- | 2048 | ; |
|
- | 2049 | ; IN: eax = socket ptr |
|
- | 2050 | ; OUT: eax = 0 on error, unchanged otherwise |
|
- | 2051 | ; ZF = set on error |
|
- | 2052 | ; |
|
- | 2053 | ;--------------------------------------------------- |
|
- | 2054 | align 4 |
|
- | 2055 | SOCKET_check: |
|
- | 2056 | ||
- | 2057 | DEBUGF 1,"SOCKET_check: %x\n", eax |
|
- | 2058 | ||
- | 2059 | push ebx |
|
967 | xchg al, ah |
2060 | mov ebx, net_sockets |
- | 2061 | ||
- | 2062 | .next_socket: |
|
- | 2063 | mov ebx, [ebx + SOCKET.NextPtr] |
|
- | 2064 | or ebx, ebx |
|
- | 2065 | jz .done |
|
- | 2066 | cmp ebx, eax |
|
- | 2067 | jnz .next_socket |
|
- | 2068 | ||
968 | mov [edx + 20 + UDP_PACKET.Checksum], ax |
2069 | .done: |
- | 2070 | mov eax, ebx |
|
- | 2071 | test eax, eax |
|
- | 2072 | pop ebx |
|
- | 2073 | ||
- | 2074 | ret |
|
- | 2075 | ||
- | 2076 | ||
- | 2077 | ||
- | 2078 | ;--------------------------------------------------- |
|
- | 2079 | ; |
|
- | 2080 | ; SOCKET_check_owner |
|
- | 2081 | ; |
|
- | 2082 | ; checks if the caller application owns the socket |
|
- | 2083 | ; |
|
- | 2084 | ; IN: eax = socket ptr |
|
969 | 2085 | ; OUT: ZF = true/false |
|
- | 2086 | ; |
|
- | 2087 | ;--------------------------------------------------- |
|
- | 2088 | align 4 |
|
- | 2089 | SOCKET_check_owner: |
|
- | 2090 | ||
- | 2091 | DEBUGF 1,"SOCKET_check_owner: %x\n", eax |
|
- | 2092 | ||
- | 2093 | push ebx |
|
- | 2094 | mov ebx, [TASK_BASE] |
|
- | 2095 | mov ebx, [ebx + TASKDATA.pid] |
|
- | 2096 | cmp [eax + SOCKET.PID], ebx |
|
- | 2097 | pop ebx |
|
- | 2098 | ||
- | 2099 | ret |
|
- | 2100 | ||
- | 2101 | ||
- | 2102 | ||
- | 2103 | ||
- | 2104 | ;------------------------------------------------------ |
|
- | 2105 | ; |
|
- | 2106 | ; SOCKET_process_end |
|
- | 2107 | ; |
|
- | 2108 | ; Kernel calls this function when a certain process ends |
|
- | 2109 | ; This function will check if the process had any open sockets |
|
- | 2110 | ; And update them accordingly |
|
- | 2111 | ; |
|
Line 970... | Line -... | ||
970 | ; Fill in the IP header checksum |
- | |
971 | GET_IHL ecx,edx ; get IP-Header length |
- | |
972 | stdcall checksum_jb, edx, ecx; buf_ptr, buf_size |
2112 | ; IN: edx = pid |
Line -... | Line 2113... | ||
- | 2113 | ; OUT: / |
|
- | 2114 | ; |
|
- | 2115 | ;------------------------------------------------------ |
|
- | 2116 | align 4 |
|
- | 2117 | SOCKET_process_end: |
|
- | 2118 | ||
- | 2119 | DEBUGF 1, "SOCKET_process_end: %x\n", edx |
|
973 | xchg al, ah |
2120 | |
- | 2121 | push ebx |
|
- | 2122 | mov ebx, net_sockets |
|
- | 2123 | ||
- | 2124 | .next_socket: |
|
- | 2125 | mov ebx, [ebx + SOCKET.NextPtr] |
|
- | 2126 | .next_socket_test: |
|
- | 2127 | test ebx, ebx |
|
- | 2128 | jz .done |
|
974 | mov [edx + IP_PACKET.HeaderChecksum], ax |
2129 | |
- | 2130 | cmp [ebx + SOCKET.PID], edx |
|
975 | 2131 | jne .next_socket |
|
976 | ; Check destination IP address. |
- |