Subversion Repositories Kolibri OS

Rev

Rev 1763 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
1159 hidnplayr 1
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2
;;                                                                 ;;
1763 hidnplayr 3
;; Copyright (C) KolibriOS team 2004-2011. All rights reserved.    ;;
1159 hidnplayr 4
;; Distributed under terms of the GNU General Public License       ;;
5
;;                                                                 ;;
1529 hidnplayr 6
;;    Written by hidnplayr@kolibrios.org,                          ;;
7
;;     and Clevermouse.                                            ;;
1159 hidnplayr 8
;;                                                                 ;;
1529 hidnplayr 9
;;       Based on code by mike.dld                                 ;;
1159 hidnplayr 10
;;                                                                 ;;
1529 hidnplayr 11
;;         GNU GENERAL PUBLIC LICENSE                              ;;
12
;;          Version 2, June 1991                                   ;;
13
;;                                                                 ;;
1159 hidnplayr 14
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
15
 
1206 hidnplayr 16
$Revision: 1773 $
1159 hidnplayr 17
 
1773 hidnplayr 18
 
1514 hidnplayr 19
virtual at 0
1249 hidnplayr 20
 
1514 hidnplayr 21
	SOCKET:
22
	.NextPtr		dd ? ; pointer to next socket in list
23
	.PrevPtr		dd ? ; pointer to previous socket in list
24
	.Number 		dd ? ; socket number
1249 hidnplayr 25
 
1514 hidnplayr 26
	.lock			dd ? ; lock mutex
1249 hidnplayr 27
 
1514 hidnplayr 28
	.PID			dd ? ; application process id
29
	.Domain 		dd ? ; INET/UNIX/..
1543 hidnplayr 30
	.Type			dd ? ; RAW/STREAM/DGRAP
31
	.Protocol		dd ? ; ICMP/IPv4/ARP/TCP/UDP
1716 hidnplayr 32
	.errorcode		dd ?
1249 hidnplayr 33
 
1514 hidnplayr 34
	.options		dd ?
1529 hidnplayr 35
	.state			dd ?
1543 hidnplayr 36
	.backlog		dw ? ; how many incomming connections that can be queued
1249 hidnplayr 37
 
1536 hidnplayr 38
	.snd_proc		dd ?
39
	.rcv_proc		dd ?
40
 
1514 hidnplayr 41
	.end:
42
end virtual
1249 hidnplayr 43
 
1514 hidnplayr 44
virtual at SOCKET.end
1254 hidnplayr 45
 
1514 hidnplayr 46
	IP_SOCKET:
1763 hidnplayr 47
	.LocalIP		rd 4
48
	.RemoteIP		rd 4
1318 hidnplayr 49
 
1514 hidnplayr 50
	.end:
51
end virtual
1159 hidnplayr 52
 
1514 hidnplayr 53
virtual at IP_SOCKET.end
1249 hidnplayr 54
 
1514 hidnplayr 55
	TCP_SOCKET:
56
 
1542 hidnplayr 57
	.LocalPort		dw ?
58
	.RemotePort		dw ?
1514 hidnplayr 59
 
60
	.OrigRemoteIP		dd ? ; original remote IP address (used to reset to LISTEN state)
61
	.OrigRemotePort 	dw ? ; original remote port (used to reset to LISTEN state)
62
 
63
	.t_state		dd ? ; TCB state
64
	.t_rxtshift		dd ?
65
	.t_rxtcur		dd ?
66
	.t_dupacks		dd ?
67
	.t_maxseg		dd ?
68
	.t_force		dd ?
69
	.t_flags		dd ?
70
 
71
;---------------
72
; RFC783 page 21
73
 
74
; send sequence
75
	.SND_UNA		dd ? ; sequence number of unack'ed sent Packets
76
	.SND_NXT		dd ? ; next send sequence number to use
77
	.SND_UP 		dd ?
78
	.SND_WL1		dd ? ; window minus one
79
	.SND_WL2		dd ? ;
80
	.ISS			dd ? ; initial send sequence number
81
	.SND_WND		dd ? ; send window
82
 
83
; receive sequence
84
	.RCV_WND		dw ? ; receive window
85
	.RCV_NXT		dd ? ; next receive sequence number to use
86
	.RCV_UP 		dd ?
87
	.IRS			dd ? ; initial receive sequence number
88
 
89
;---------------------
90
; Additional variables
91
 
92
; receive variables
93
	.RCV_ADV		dd ?
94
 
95
; retransmit variables
96
	.SND_MAX		dd ?
97
 
98
; congestion control
99
	.SND_CWND		dd ?
100
	.SND_SSTHRESH		dd ?
101
 
102
;----------------------
103
; Transmit timing stuff
104
	.t_idle 		dd ?
105
	.t_rtt			dd ?
106
	.t_rtseq		dd ?
107
	.t_srtt 		dd ?
108
	.t_rttvar		dd ?
109
	.t_rttmin		dd ?
110
	.max_sndwnd		dd ?
111
 
112
;-----------------
113
; Out-of-band data
114
	.t_oobflags		dd ?
115
	.t_iobc 		dd ?
116
	.t_softerror		dd ?
117
 
118
 
119
;---------
120
; RFC 1323
121
	.SND_SCALE		db ? ; Scale factor
122
	.RCV_SCALE		db ?
123
	.request_r_scale	db ?
124
	.requested_s_scale	dd ?
125
 
126
	.ts_recent		dd ?
127
	.ts_recent_age		dd ?
128
	.last_ack_sent		dd ?
129
 
1519 hidnplayr 130
 
131
;-------
132
; Timers
1529 hidnplayr 133
	.timer_retransmission	dw ? ; rexmt
1519 hidnplayr 134
	.timer_ack		dw ?
135
	.timer_persist		dw ?
1529 hidnplayr 136
	.timer_keepalive	dw ? ; keepalive/syn timeout
137
	.timer_timed_wait	dw ? ; also used as 2msl timer
1519 hidnplayr 138
 
1249 hidnplayr 139
	.end:
1514 hidnplayr 140
end virtual
1249 hidnplayr 141
 
1514 hidnplayr 142
virtual at IP_SOCKET.end
1249 hidnplayr 143
 
1514 hidnplayr 144
	UDP_SOCKET:
1249 hidnplayr 145
 
1542 hidnplayr 146
	.LocalPort		dw ?
147
	.RemotePort		dw ?
1514 hidnplayr 148
	.firstpacket		db ?
1249 hidnplayr 149
 
150
	.end:
1514 hidnplayr 151
end virtual
1249 hidnplayr 152
 
1514 hidnplayr 153
virtual at IP_SOCKET.end
1249 hidnplayr 154
 
1514 hidnplayr 155
	ICMP_SOCKET:
156
 
1542 hidnplayr 157
	.Identifier		dw ?
1514 hidnplayr 158
 
159
	.end:
160
end virtual
161
 
1529 hidnplayr 162
struc	RING_BUFFER {
163
	.start_ptr		dd ? ; Pointer to start of buffer
164
	.end_ptr		dd ? ; pointer to end of buffer
165
	.read_ptr		dd ? ; Read pointer
166
	.write_ptr		dd ? ; Write pointer
167
	.size			dd ? ; Number of bytes buffered
1533 hidnplayr 168
	.end:
1529 hidnplayr 169
}
1514 hidnplayr 170
 
1529 hidnplayr 171
virtual at 0
172
 
173
	RING_BUFFER	RING_BUFFER
174
 
175
end virtual
176
 
177
virtual at TCP_SOCKET.end
178
 
179
 STREAM_SOCKET:
1533 hidnplayr 180
	.rcv	rd     RING_BUFFER.end/4
181
	.snd	rd     RING_BUFFER.end/4
1529 hidnplayr 182
	.end:
183
 
184
end virtual
185
 
1274 hidnplayr 186
struct	socket_queue_entry
187
	.data_ptr	dd ?
1514 hidnplayr 188
	.buf_ptr	dd ?
1274 hidnplayr 189
	.data_size	dd ?
190
	.size:
191
ends
192
 
1514 hidnplayr 193
 
1249 hidnplayr 194
SOCKETBUFFSIZE		equ 4096     ; in bytes
1514 hidnplayr 195
 
1249 hidnplayr 196
SOCKET_QUEUE_SIZE	equ 10	     ; maximum number ofincoming packets queued for 1 socket
1514 hidnplayr 197
; the incoming packet queue for sockets is placed in the socket struct itself, at this location from start
1543 hidnplayr 198
SOCKET_QUEUE_LOCATION	equ (SOCKETBUFFSIZE - SOCKET_QUEUE_SIZE*socket_queue_entry.size - queue.data)
1249 hidnplayr 199
 
1159 hidnplayr 200
uglobal
1514 hidnplayr 201
	net_sockets	rd 4
1543 hidnplayr 202
	last_socket_num dd ?
1159 hidnplayr 203
	last_UDP_port	dw ? ; These values give the number of the last used ephemeral port
204
	last_TCP_port	dw ? ;
205
endg
206
 
207
 
1257 hidnplayr 208
;-----------------------------------------------------------------
1159 hidnplayr 209
;
210
; SOCKET_init
211
;
1257 hidnplayr 212
;-----------------------------------------------------------------
1529 hidnplayr 213
macro	SOCKET_init {
1159 hidnplayr 214
 
1514 hidnplayr 215
	xor	eax, eax
216
	mov	edi, net_sockets
1543 hidnplayr 217
	mov	ecx, 5
1514 hidnplayr 218
	rep	stosd
1159 hidnplayr 219
 
1529 hidnplayr 220
       @@:
221
	pseudo_random eax
222
	cmp	ax, MIN_EPHEMERAL_PORT
223
	jl	@r
224
	cmp	ax, MAX_EPHEMERAL_PORT
225
	jg	@r
226
	mov	[last_UDP_port], ax
227
 
228
       @@:
229
	pseudo_random eax
230
	cmp	ax, MIN_EPHEMERAL_PORT
231
	jl	@r
232
	cmp	ax, MAX_EPHEMERAL_PORT
233
	jg	@r
234
	mov	[last_TCP_port], ax
235
 
236
}
237
 
238
 
1257 hidnplayr 239
;-----------------------------------------------------------------
1159 hidnplayr 240
;
241
; Socket API (function 74)
242
;
1257 hidnplayr 243
;-----------------------------------------------------------------
1159 hidnplayr 244
align 4
245
sys_socket:
1542 hidnplayr 246
	cmp	ebx, 9		; highest possible number
1529 hidnplayr 247
	jg	@f
1542 hidnplayr 248
	jmp	dword [sock_sysfn_table + 4*ebx]
1529 hidnplayr 249
       @@:
250
	cmp	ebx, 255
251
	jz	SOCKET_debug
1159 hidnplayr 252
 
1529 hidnplayr 253
s_error:
254
	DEBUGF	1,"socket error\n"
255
	mov	dword [esp+32], -1
256
 
257
	ret
258
 
1536 hidnplayr 259
align 4
1529 hidnplayr 260
sock_sysfn_table:
1514 hidnplayr 261
	dd	SOCKET_open	; 0
262
	dd	SOCKET_close	; 1
263
	dd	SOCKET_bind	; 2
264
	dd	SOCKET_listen	; 3
265
	dd	SOCKET_connect	; 4
266
	dd	SOCKET_accept	; 5
267
	dd	SOCKET_send	; 6
268
	dd	SOCKET_receive	; 7
1542 hidnplayr 269
	dd	SOCKET_set_opt	; 8
270
	dd	SOCKET_get_opt	; 9
1159 hidnplayr 271
 
1257 hidnplayr 272
;-----------------------------------------------------------------
1159 hidnplayr 273
;
274
; SOCKET_open
275
;
276
;  IN:  domain in ecx
277
;       type in edx
1196 hidnplayr 278
;       protocol in esi
1159 hidnplayr 279
;  OUT: eax is socket num, -1 on error
280
;
1257 hidnplayr 281
;-----------------------------------------------------------------
1206 hidnplayr 282
align 4
1514 hidnplayr 283
SOCKET_open:
1159 hidnplayr 284
 
1536 hidnplayr 285
	DEBUGF	1,"SOCKET_open: domain: %u, type: %u protocol: %x\n", ecx, edx, esi
1159 hidnplayr 286
 
1514 hidnplayr 287
	call	SOCKET_alloc
1185 hidnplayr 288
	jz	s_error
1159 hidnplayr 289
 
1542 hidnplayr 290
	mov	[esp+32], edi			; return socketnumber
291
 
1514 hidnplayr 292
	mov	[eax + SOCKET.Domain], ecx
293
	mov	[eax + SOCKET.Type], edx
294
	mov	[eax + SOCKET.Protocol], esi
1159 hidnplayr 295
 
1529 hidnplayr 296
	cmp	ecx, AF_INET4
1536 hidnplayr 297
	jne	.no_inet4
1529 hidnplayr 298
 
1542 hidnplayr 299
	cmp	edx, SOCK_DGRAM
1536 hidnplayr 300
	je	.udp
301
 
1542 hidnplayr 302
	cmp	edx, SOCK_STREAM
1536 hidnplayr 303
	je	.tcp
1529 hidnplayr 304
 
1541 hidnplayr 305
	cmp	edx, SOCK_RAW
306
	je	.raw
307
 
1536 hidnplayr 308
  .no_inet4:
309
	ret
310
 
1542 hidnplayr 311
align 4
312
  .raw:
1543 hidnplayr 313
	test	esi, esi       ; IP_PROTO_IP
314
	jz	.ip
1529 hidnplayr 315
 
1542 hidnplayr 316
	cmp	esi, IP_PROTO_ICMP
317
	je	.icmp
1529 hidnplayr 318
 
1542 hidnplayr 319
	cmp	esi, IP_PROTO_UDP
320
	je	.udp
1533 hidnplayr 321
 
1542 hidnplayr 322
	cmp	esi, IP_PROTO_TCP
323
	je	.tcp
1536 hidnplayr 324
 
1159 hidnplayr 325
	ret
326
 
1542 hidnplayr 327
align 4
1536 hidnplayr 328
  .udp:
1542 hidnplayr 329
	mov	[eax + SOCKET.Protocol], IP_PROTO_UDP
1536 hidnplayr 330
	mov	[eax + SOCKET.snd_proc], SOCKET_send_udp
1541 hidnplayr 331
	mov	[eax + SOCKET.rcv_proc], SOCKET_receive_dgram
1529 hidnplayr 332
	ret
333
 
1542 hidnplayr 334
align 4
335
  .tcp:
336
	mov	[eax + SOCKET.Protocol], IP_PROTO_TCP
1543 hidnplayr 337
	mov	[eax + SOCKET.snd_proc], SOCKET_send_tcp
338
	mov	[eax + SOCKET.rcv_proc], SOCKET_receive_tcp
339
	ret
1529 hidnplayr 340
 
341
 
1543 hidnplayr 342
align 4
343
  .ip:
344
	mov	[eax + SOCKET.snd_proc], SOCKET_send_ip
345
	mov	[eax + SOCKET.rcv_proc], SOCKET_receive_dgram
1541 hidnplayr 346
	ret
347
 
1542 hidnplayr 348
 
349
align 4
1541 hidnplayr 350
  .icmp:
351
	mov	[eax + SOCKET.snd_proc], SOCKET_send_icmp
352
	mov	[eax + SOCKET.rcv_proc], SOCKET_receive_dgram
353
	ret
354
 
355
 
356
 
1257 hidnplayr 357
;-----------------------------------------------------------------
1159 hidnplayr 358
;
359
; SOCKET_bind
360
;
361
;  IN:  socket number in ecx
362
;       pointer to sockaddr struct in edx
363
;       length of that struct in esi
364
;  OUT: 0 on success
365
;
1257 hidnplayr 366
;-----------------------------------------------------------------
1206 hidnplayr 367
align 4
1514 hidnplayr 368
SOCKET_bind:
1159 hidnplayr 369
 
1514 hidnplayr 370
	DEBUGF	1,"socket_bind: socknum: %u sockaddr: %x, length: %u\n", ecx, edx, esi
1159 hidnplayr 371
 
1514 hidnplayr 372
	call	SOCKET_num_to_ptr
1185 hidnplayr 373
	jz	s_error
1159 hidnplayr 374
 
375
	cmp	esi, 2
1185 hidnplayr 376
	jl	s_error
1159 hidnplayr 377
 
378
	cmp	word [edx], AF_INET4
1249 hidnplayr 379
	je	.af_inet4
1159 hidnplayr 380
 
1249 hidnplayr 381
	cmp	word [edx], AF_UNIX
382
	je	.af_unix
383
 
384
	jmp	s_error
385
 
386
  .af_unix:
387
	; TODO: write code here
388
 
1514 hidnplayr 389
	mov	dword [esp+32], 0
1249 hidnplayr 390
	ret
391
 
1159 hidnplayr 392
  .af_inet4:
393
 
1514 hidnplayr 394
	DEBUGF	1,"af_inet4\n"
395
 
1159 hidnplayr 396
	cmp	esi, 6
1185 hidnplayr 397
	jl	s_error
1159 hidnplayr 398
 
1543 hidnplayr 399
	push	word [edx + 2]
400
	pop	word [eax + UDP_SOCKET.LocalPort]
1159 hidnplayr 401
 
1543 hidnplayr 402
	push	dword [edx + 4]
403
	pop	[eax + IP_SOCKET.LocalIP]
1159 hidnplayr 404
 
405
	DEBUGF	1,"local ip: %u.%u.%u.%u\n",\
1514 hidnplayr 406
	[eax + IP_SOCKET.LocalIP + 0]:1,[eax + IP_SOCKET.LocalIP + 1]:1,\
407
	[eax + IP_SOCKET.LocalIP + 2]:1,[eax + IP_SOCKET.LocalIP + 3]:1
1159 hidnplayr 408
 
1514 hidnplayr 409
	mov	dword [esp+32], 0
1159 hidnplayr 410
	ret
411
 
412
 
413
 
414
 
1257 hidnplayr 415
;-----------------------------------------------------------------
1159 hidnplayr 416
;
417
; SOCKET_connect
418
;
419
;  IN:  socket number in ecx
420
;       pointer to sockaddr struct in edx
421
;       length of that struct in esi
422
;  OUT: 0 on success
423
;
1257 hidnplayr 424
;-----------------------------------------------------------------
1159 hidnplayr 425
align 4
1514 hidnplayr 426
SOCKET_connect:
1159 hidnplayr 427
 
1541 hidnplayr 428
	DEBUGF	1,"SOCKET_connect: socknum: %u sockaddr: %x, length: %u\n", ecx, edx, esi
1159 hidnplayr 429
 
1514 hidnplayr 430
	call	SOCKET_num_to_ptr
1185 hidnplayr 431
	jz	s_error
1159 hidnplayr 432
 
1254 hidnplayr 433
	cmp	esi, 8
1185 hidnplayr 434
	jl	s_error
1159 hidnplayr 435
 
436
	cmp	word [edx], AF_INET4
437
	je	.af_inet4
438
 
1185 hidnplayr 439
	jmp	s_error
1159 hidnplayr 440
 
441
  .af_inet4:
1543 hidnplayr 442
	cmp	[eax + IP_SOCKET.LocalIP], 0
443
	jne	@f
444
	push	[IP_LIST]
445
	pop	[eax + IP_SOCKET.LocalIP]
446
       @@:
1159 hidnplayr 447
 
1542 hidnplayr 448
	cmp	[eax + SOCKET.Protocol], IP_PROTO_UDP
1159 hidnplayr 449
	je	.udp
450
 
1542 hidnplayr 451
	cmp	[eax + SOCKET.Protocol], IP_PROTO_TCP
1206 hidnplayr 452
	je	.tcp
1159 hidnplayr 453
 
1542 hidnplayr 454
	cmp	[eax + SOCKET.Protocol], IP_PROTO_IP
455
	je	.ip
1541 hidnplayr 456
 
1542 hidnplayr 457
	cmp	[eax + SOCKET.Protocol], IP_PROTO_ICMP
458
	je	.ip
459
 
1185 hidnplayr 460
	jmp	s_error
1159 hidnplayr 461
 
1542 hidnplayr 462
align 4
1254 hidnplayr 463
  .udp:
1543 hidnplayr 464
	lea	ebx, [eax + SOCKET.lock]
465
	call	wait_mutex
466
 
467
	push	word [edx + 2]
468
	pop	[eax + UDP_SOCKET.RemotePort]
469
 
470
	push	dword [edx + 4]
471
	pop	[eax + IP_SOCKET.RemoteIP]
472
 
473
	cmp	[eax + UDP_SOCKET.LocalPort], 0
474
	jne	@f
475
	call	SOCKET_find_port
476
       @@:
477
 
1514 hidnplayr 478
	mov	[eax + UDP_SOCKET.firstpacket], 0
1159 hidnplayr 479
 
1543 hidnplayr 480
	push	eax
481
	init_queue (eax + SOCKET_QUEUE_LOCATION)	; Set up data receiving queue
1733 hidnplayr 482
	pop	eax
1159 hidnplayr 483
 
1543 hidnplayr 484
	mov	[eax + SOCKET.lock], 0
1514 hidnplayr 485
	mov	dword [esp+32], 0
1159 hidnplayr 486
	ret
487
 
1542 hidnplayr 488
align 4
1254 hidnplayr 489
  .tcp:
1514 hidnplayr 490
	lea	ebx, [eax + SOCKET.lock]
1281 hidnplayr 491
	call	wait_mutex
1159 hidnplayr 492
 
1543 hidnplayr 493
	push	word [edx + 2]
494
	pop	[eax + TCP_SOCKET.RemotePort]
1159 hidnplayr 495
 
1543 hidnplayr 496
	push	dword [edx + 4]
497
	pop	[eax + IP_SOCKET.RemoteIP]
1159 hidnplayr 498
 
1543 hidnplayr 499
	cmp	[eax + TCP_SOCKET.LocalPort], 0
500
	jne	@f
501
	call	SOCKET_find_port
502
       @@:
1159 hidnplayr 503
 
1529 hidnplayr 504
	mov	[eax + TCP_SOCKET.timer_persist], 0
505
	mov	[eax + TCP_SOCKET.t_state], TCB_SYN_SENT
1733 hidnplayr 506
	push	[TCP_sequence_num]
1529 hidnplayr 507
	add	[TCP_sequence_num], 6400
1733 hidnplayr 508
	pop	[eax + TCP_SOCKET.ISS]
1533 hidnplayr 509
	mov	[eax + TCP_SOCKET.timer_keepalive], TCP_time_keep_init
1519 hidnplayr 510
 
1762 hidnplayr 511
	mov	[eax + TCP_SOCKET.t_maxseg], 1480	;;;;;
512
 
1533 hidnplayr 513
	TCP_sendseqinit eax
1529 hidnplayr 514
 
1543 hidnplayr 515
;        mov     [ebx + TCP_SOCKET.timer_retransmission],   ;; todo: create macro to set retransmission timer
1533 hidnplayr 516
 
1543 hidnplayr 517
	mov	ebx, eax
1159 hidnplayr 518
 
1543 hidnplayr 519
	lea	eax, [ebx + STREAM_SOCKET.snd]
520
	call	SOCKET_ring_create
521
 
522
	lea	eax, [ebx + STREAM_SOCKET.rcv]
523
	call	SOCKET_ring_create
524
 
525
	mov	[ebx + SOCKET.lock], 0
1733 hidnplayr 526
 
527
	mov	eax, ebx
528
	call	TCP_output
529
 
1543 hidnplayr 530
	mov	dword [esp+32], 0
1159 hidnplayr 531
	ret
532
 
1542 hidnplayr 533
align 4
534
  .ip:
1543 hidnplayr 535
	lea	ebx, [eax + SOCKET.lock]
536
	call	wait_mutex
537
 
1541 hidnplayr 538
	push	dword [edx + 4]
539
	pop	dword [eax + IP_SOCKET.RemoteIP]
1159 hidnplayr 540
 
1543 hidnplayr 541
	push	eax
542
	init_queue (eax + SOCKET_QUEUE_LOCATION)	; Set up data receiving queue
543
	pop	eax
544
 
545
	mov	[eax + SOCKET.lock], 0
546
	mov	dword [esp+32], 0
1541 hidnplayr 547
	ret
548
 
549
 
1257 hidnplayr 550
;-----------------------------------------------------------------
1159 hidnplayr 551
;
552
; SOCKET_listen
553
;
554
;  IN:  socket number in ecx
555
;       backlog in edx
556
;  OUT: eax is socket num, -1 on error
557
;
1257 hidnplayr 558
;-----------------------------------------------------------------
1206 hidnplayr 559
align 4
1514 hidnplayr 560
SOCKET_listen:
1159 hidnplayr 561
 
1541 hidnplayr 562
	DEBUGF	1,"SOCKET_listen: socknum: %u backlog: %u\n", ecx, edx
1159 hidnplayr 563
 
1514 hidnplayr 564
	call	SOCKET_num_to_ptr
1185 hidnplayr 565
	jz	s_error
1159 hidnplayr 566
 
1514 hidnplayr 567
	cmp	word [eax + SOCKET.Domain], AF_INET4
1254 hidnplayr 568
	jne	s_error
569
 
1542 hidnplayr 570
	cmp	[eax + SOCKET.Protocol], IP_PROTO_TCP
1254 hidnplayr 571
	jne	s_error
572
 
1543 hidnplayr 573
	cmp	[eax + TCP_SOCKET.LocalPort], 0
574
	je	s_error
1514 hidnplayr 575
 
1543 hidnplayr 576
	cmp	[eax + IP_SOCKET.LocalIP], 0
577
	jne	@f
578
	push	[IP_LIST]
579
	pop	[eax + IP_SOCKET.LocalIP]
580
       @@:
581
 
1159 hidnplayr 582
	cmp	edx, MAX_backlog
1543 hidnplayr 583
	jle	@f
1514 hidnplayr 584
	mov	edx, MAX_backlog
1543 hidnplayr 585
       @@:
1159 hidnplayr 586
 
1543 hidnplayr 587
	mov	[eax + SOCKET.backlog], dx
588
	or	[eax + SOCKET.options], SO_ACCEPTCON
1514 hidnplayr 589
	mov	[eax + TCP_SOCKET.t_state], TCB_LISTEN
1159 hidnplayr 590
 
1543 hidnplayr 591
	push	eax
592
	init_queue (eax + SOCKET_QUEUE_LOCATION)		; Set up sockets queue
593
	pop	eax
594
 
1159 hidnplayr 595
	mov	dword [esp+32], 0
1514 hidnplayr 596
 
1159 hidnplayr 597
	ret
598
 
599
 
1257 hidnplayr 600
;-----------------------------------------------------------------
1159 hidnplayr 601
;
602
; SOCKET_accept
603
;
604
;  IN:  socket number in ecx
605
;       addr in edx
606
;       addrlen in esi
607
;  OUT: eax is socket num, -1 on error
608
;
1257 hidnplayr 609
;-----------------------------------------------------------------
1206 hidnplayr 610
align 4
1514 hidnplayr 611
SOCKET_accept:
1159 hidnplayr 612
 
1541 hidnplayr 613
	DEBUGF	1,"SOCKET_accept: socknum: %u sockaddr: %x, length: %u\n", ecx, edx, esi
1159 hidnplayr 614
 
1514 hidnplayr 615
	call	SOCKET_num_to_ptr
1185 hidnplayr 616
	jz	s_error
1159 hidnplayr 617
 
1543 hidnplayr 618
	test	[eax + SOCKET.options], SO_ACCEPTCON
619
	jz	s_error
620
 
1514 hidnplayr 621
	cmp	word [eax + SOCKET.Domain], AF_INET4
1543 hidnplayr 622
	jne	s_error
1249 hidnplayr 623
 
1542 hidnplayr 624
	cmp	[eax + SOCKET.Protocol], IP_PROTO_TCP
1543 hidnplayr 625
	jne	s_error
1249 hidnplayr 626
 
1543 hidnplayr 627
	get_from_queue (eax + SOCKET_QUEUE_LOCATION), MAX_backlog, 4, s_error
1249 hidnplayr 628
 
1543 hidnplayr 629
	mov	eax, [esi]
630
	call	SOCKET_ptr_to_num
631
	jz	s_error
632
	mov	dword [esp+32], eax
1159 hidnplayr 633
	ret
1514 hidnplayr 634
 
1159 hidnplayr 635
 
1257 hidnplayr 636
;-----------------------------------------------------------------
1159 hidnplayr 637
;
638
; SOCKET_close
639
;
640
;  IN:  socket number in ecx
641
;  OUT: eax is socket num, -1 on error
642
;
1257 hidnplayr 643
;-----------------------------------------------------------------
1206 hidnplayr 644
align 4
1514 hidnplayr 645
SOCKET_close:
1159 hidnplayr 646
 
1541 hidnplayr 647
	DEBUGF	1,"SOCKET_close: socknum: %u\n", ecx
1159 hidnplayr 648
 
1514 hidnplayr 649
	call	SOCKET_num_to_ptr
1185 hidnplayr 650
	jz	s_error
1159 hidnplayr 651
 
1514 hidnplayr 652
	cmp	[eax + SOCKET.Domain], AF_INET4
1249 hidnplayr 653
	jne	s_error
1159 hidnplayr 654
 
1542 hidnplayr 655
	cmp	[eax + SOCKET.Protocol], IP_PROTO_UDP
1514 hidnplayr 656
	je	.free
1159 hidnplayr 657
 
1542 hidnplayr 658
	cmp	[eax + SOCKET.Protocol], IP_PROTO_ICMP
1514 hidnplayr 659
	je	.free
1159 hidnplayr 660
 
1542 hidnplayr 661
	cmp	[eax + SOCKET.Protocol], IP_PROTO_IP
662
	je	.free
663
 
664
	cmp	[eax + SOCKET.Protocol], IP_PROTO_TCP
1206 hidnplayr 665
	je	.tcp
1159 hidnplayr 666
 
1185 hidnplayr 667
	jmp	s_error
1159 hidnplayr 668
 
669
  .tcp:
1536 hidnplayr 670
	cmp	[eax + TCP_SOCKET.t_state], TCB_SYN_RECEIVED	; state must be LISTEN, SYN_SENT or CLOSED
671
	jl	.free
1318 hidnplayr 672
 
1536 hidnplayr 673
	call	TCP_output
674
	mov	dword [esp+32], 0
1159 hidnplayr 675
 
1536 hidnplayr 676
	ret
1159 hidnplayr 677
 
1514 hidnplayr 678
  .free:
679
	call	SOCKET_free
680
	mov	dword [esp+32], 0
1159 hidnplayr 681
 
682
	ret
683
 
684
 
1257 hidnplayr 685
;-----------------------------------------------------------------
1159 hidnplayr 686
;
687
; SOCKET_receive
688
;
689
;  IN:  socket number in ecx
1249 hidnplayr 690
;       addr to buffer in edx
691
;       length of buffer in esi
1159 hidnplayr 692
;       flags in edi
693
;  OUT: eax is number of bytes copied, -1 on error
694
;
1257 hidnplayr 695
;-----------------------------------------------------------------
1206 hidnplayr 696
align 4
1514 hidnplayr 697
SOCKET_receive:
1159 hidnplayr 698
 
1536 hidnplayr 699
	DEBUGF	1,"SOCKET_receive: socknum: %u bufaddr: %x, buflength: %u, flags: %x, ", ecx, edx, esi, edi
1514 hidnplayr 700
 
701
	call	SOCKET_num_to_ptr
1185 hidnplayr 702
	jz	s_error
1159 hidnplayr 703
 
1536 hidnplayr 704
	jmp	[eax + SOCKET.rcv_proc]
1533 hidnplayr 705
 
1536 hidnplayr 706
 
707
align 4
1541 hidnplayr 708
SOCKET_receive_dgram:
1536 hidnplayr 709
 
1541 hidnplayr 710
	DEBUGF	1,"SOCKET_receive: DGRAM\n"
1536 hidnplayr 711
 
1281 hidnplayr 712
	mov	ebx, esi
1514 hidnplayr 713
	mov	edi, edx					; addr to buffer
1159 hidnplayr 714
 
1536 hidnplayr 715
	get_from_queue (eax + SOCKET_QUEUE_LOCATION), SOCKET_QUEUE_SIZE, socket_queue_entry.size, s_error	; destroys esi and ecx
716
 
1249 hidnplayr 717
	mov	ecx, [esi + socket_queue_entry.data_size]
718
	DEBUGF	1,"Got %u bytes of data\n", ecx
1159 hidnplayr 719
 
1281 hidnplayr 720
	cmp	ecx, ebx
1536 hidnplayr 721
	jg	.too_small
1514 hidnplayr 722
 
1536 hidnplayr 723
	push	[esi + socket_queue_entry.buf_ptr]		; save the buffer addr so we can clear it later
1514 hidnplayr 724
	mov	esi, [esi + socket_queue_entry.data_ptr]
1249 hidnplayr 725
	DEBUGF	1,"Source buffer: %x, real addr: %x\n", [esp], esi
1536 hidnplayr 726
	mov	dword[esp+32+4], ecx				; return number of bytes copied
1159 hidnplayr 727
 
1514 hidnplayr 728
; copy the data
1249 hidnplayr 729
	shr	ecx, 1
730
	jnc	.nb
731
	movsb
1536 hidnplayr 732
  .nb:
733
	shr	ecx, 1
1249 hidnplayr 734
	jnc	.nw
735
	movsw
1536 hidnplayr 736
  .nw:
737
	test	ecx, ecx
1274 hidnplayr 738
	jz	.nd
739
	rep	movsd
1536 hidnplayr 740
  .nd:
1159 hidnplayr 741
 
1536 hidnplayr 742
	call	kernel_free					; remove the packet
1533 hidnplayr 743
	ret
1514 hidnplayr 744
 
1536 hidnplayr 745
  .too_small:
1533 hidnplayr 746
 
1536 hidnplayr 747
	DEBUGF	1,"Buffer too small...\n"
748
	jmp	s_error
749
 
750
align 4
751
SOCKET_receive_tcp:
752
 
1541 hidnplayr 753
	DEBUGF	1,"SOCKET_receive: TCP\n"
1536 hidnplayr 754
 
1533 hidnplayr 755
	mov	ecx, esi
756
	mov	edi, edx
757
	add	eax, STREAM_SOCKET.rcv
758
	call	SOCKET_ring_read
1534 hidnplayr 759
	call	SOCKET_ring_free
1533 hidnplayr 760
 
1536 hidnplayr 761
	mov	dword[esp+32], ecx				; return number of bytes copied
1533 hidnplayr 762
 
1159 hidnplayr 763
	ret
764
 
765
 
1257 hidnplayr 766
;-----------------------------------------------------------------
1159 hidnplayr 767
;
768
; SOCKET_send
769
;
770
;
771
;  IN:  socket number in ecx
1206 hidnplayr 772
;       pointer to data in edx
773
;       datalength in esi
1159 hidnplayr 774
;       flags in edi
775
;  OUT: -1 on error
776
;
1257 hidnplayr 777
;-----------------------------------------------------------------
1206 hidnplayr 778
align 4
1514 hidnplayr 779
SOCKET_send:
1159 hidnplayr 780
 
1541 hidnplayr 781
	DEBUGF	1,"SOCKET_send: socknum: %u data ptr: %x, length: %u, flags: %x, ", ecx, edx, esi, edi
1159 hidnplayr 782
 
1514 hidnplayr 783
	call	SOCKET_num_to_ptr
1185 hidnplayr 784
	jz	s_error
1159 hidnplayr 785
 
1763 hidnplayr 786
	mov	ecx, esi
787
	mov	esi, edx
788
 
1536 hidnplayr 789
	jmp	[eax + SOCKET.snd_proc]
1206 hidnplayr 790
 
791
 
1536 hidnplayr 792
align 4
793
SOCKET_send_udp:
1529 hidnplayr 794
 
1541 hidnplayr 795
	DEBUGF	1,"SOCKET_send: UDP\n"
1159 hidnplayr 796
 
1514 hidnplayr 797
	call	UDP_output
1159 hidnplayr 798
 
1514 hidnplayr 799
	mov	dword [esp+32], 0
1159 hidnplayr 800
	ret
801
 
802
 
1536 hidnplayr 803
align 4
804
SOCKET_send_tcp:
1254 hidnplayr 805
 
1541 hidnplayr 806
	DEBUGF	1,"SOCKET_send: TCP\n"
1254 hidnplayr 807
 
1533 hidnplayr 808
	push	eax
809
	add	eax, STREAM_SOCKET.snd
810
	call	SOCKET_ring_write
811
	pop	eax
1536 hidnplayr 812
 
1514 hidnplayr 813
	call	TCP_output
1254 hidnplayr 814
 
1249 hidnplayr 815
	mov	[esp+32], eax
816
	ret
1159 hidnplayr 817
 
1249 hidnplayr 818
 
1543 hidnplayr 819
align 4
820
SOCKET_send_ip:
1249 hidnplayr 821
 
1543 hidnplayr 822
	DEBUGF	1,"type: IP\n"
823
 
824
	call	IPv4_output_raw
825
 
1763 hidnplayr 826
	mov	[esp+32], eax
1543 hidnplayr 827
	ret
828
 
1541 hidnplayr 829
align 4
830
SOCKET_send_icmp:
1249 hidnplayr 831
 
1541 hidnplayr 832
	DEBUGF	1,"SOCKET_send: ICMP\n"
833
 
834
	call	ICMP_output_raw
835
 
836
	mov	dword [esp+32], 0
837
	ret
838
 
839
 
840
 
841
 
1257 hidnplayr 842
;-----------------------------------------------------------------
1256 clevermous 843
;
1257 hidnplayr 844
; SOCKET_get_options
1256 clevermous 845
;
1514 hidnplayr 846
;  IN:  ecx = socket number
847
;       edx = pointer to the options:
1257 hidnplayr 848
;               dd      level, optname, optval, optlen
1256 clevermous 849
;  OUT: -1 on error
850
;
851
; At moment, uses only pseudo-optname -2 for get last_ack_number for TCP.
852
; TODO: find best way to notify that send()'ed data were acknowledged
1299 clevermous 853
; Also pseudo-optname -3 is valid and returns socket state, one of TCB_*.
1256 clevermous 854
;
1257 hidnplayr 855
;-----------------------------------------------------------------
856
align 4
1514 hidnplayr 857
SOCKET_get_opt:
1257 hidnplayr 858
 
1536 hidnplayr 859
	DEBUGF	1,"SOCKET_get_opt\n"
1514 hidnplayr 860
 
861
	call	SOCKET_num_to_ptr
862
	jz	s_error
863
 
1256 clevermous 864
	cmp	dword [edx], IP_PROTO_TCP
1514 hidnplayr 865
	jnz	s_error
1256 clevermous 866
	cmp	dword [edx+4], -2
1299 clevermous 867
	jz	@f
868
	cmp	dword [edx+4], -3
1514 hidnplayr 869
	jnz	s_error
1299 clevermous 870
@@:
1514 hidnplayr 871
;        mov     eax, [edx+12]
872
;        test    eax, eax
873
;        jz      .fail
874
;        cmp     dword [eax], 4
875
;        mov     dword [eax], 4
876
;        jb      .fail
877
;        stdcall net_socket_num_to_addr, ecx
878
;        test    eax, eax
879
;        jz      .fail
880
;        ; todo: check that eax is really TCP socket
881
;        mov     ecx, [eax + TCP_SOCKET.last_ack_number]
882
;        cmp     dword [edx+4], -2
883
;        jz      @f
884
;        mov     ecx, [eax + TCP_SOCKET.state]
1299 clevermous 885
@@:
1256 clevermous 886
	mov	eax, [edx+8]
887
	test	eax, eax
888
	jz	@f
889
	mov	[eax], ecx
890
@@:
1257 hidnplayr 891
	mov	dword [esp+32], 0
1256 clevermous 892
	ret
1159 hidnplayr 893
 
894
 
1529 hidnplayr 895
 
1542 hidnplayr 896
 
897
align 4
898
SOCKET_set_opt:
899
 
900
	ret
901
 
902
 
903
 
1257 hidnplayr 904
;-----------------------------------------------------------------
1206 hidnplayr 905
;
1529 hidnplayr 906
; SOCKET_debug
907
;
908
;  Copies socket variables to application buffer
909
;
910
;  IN:  ecx = socket number
911
;       edx = pointer to buffer
912
;
913
;  OUT: -1 on error
914
;-----------------------------------------------------------------
915
align 4
916
SOCKET_debug:
917
 
918
	DEBUGF	1,"socket_debug\n"
919
 
920
	call	SOCKET_num_to_ptr
921
	jz	s_error
922
 
923
	mov	esi, eax
924
	mov	edi, edx
925
	mov	ecx, SOCKETBUFFSIZE/4
926
	rep	movsd
927
 
928
	mov	dword [esp+32], 0
929
	ret
930
 
931
 
932
;-----------------------------------------------------------------
933
;
1514 hidnplayr 934
; SOCKET_find_port
1206 hidnplayr 935
;
1514 hidnplayr 936
; Fills in the local port number for TCP and UDP sockets
937
; This procedure always works because the number of sockets is
938
; limited to a smaller number then the number of possible ports
1206 hidnplayr 939
;
1514 hidnplayr 940
;  IN:  eax = socket pointer
941
;  OUT: /
1206 hidnplayr 942
;
1257 hidnplayr 943
;-----------------------------------------------------------------
1206 hidnplayr 944
align 4
1514 hidnplayr 945
SOCKET_find_port:
1159 hidnplayr 946
 
1536 hidnplayr 947
	DEBUGF	1,"SOCKET_find_port\n"
1159 hidnplayr 948
 
1514 hidnplayr 949
	push	ebx esi ecx
950
 
1542 hidnplayr 951
	cmp	[eax + SOCKET.Protocol], IP_PROTO_UDP
1206 hidnplayr 952
	je	.udp
1159 hidnplayr 953
 
1542 hidnplayr 954
	cmp	[eax + SOCKET.Protocol], IP_PROTO_TCP
1206 hidnplayr 955
	je	.tcp
1159 hidnplayr 956
 
1514 hidnplayr 957
	jmp	.error
958
 
959
  .done:
960
	mov	[eax + UDP_SOCKET.LocalPort], bx
961
  .error:
962
	pop	ecx esi ebx
963
	ret
964
 
1206 hidnplayr 965
  .udp:
966
	mov	bx, [last_UDP_port]
1514 hidnplayr 967
	call	.findit
968
	mov	[last_UDP_port], bx
969
	jmp	.done
1206 hidnplayr 970
 
971
  .tcp:
972
	mov	bx, [last_TCP_port]
1514 hidnplayr 973
	call	.findit
974
	mov	[last_TCP_port], bx
975
	jmp	.done
1206 hidnplayr 976
 
977
 
1514 hidnplayr 978
  .restart:
979
	mov	bx, MIN_EPHEMERAL_PORT
980
  .findit:
1206 hidnplayr 981
	inc	bx
982
 
983
	cmp	bx, MAX_EPHEMERAL_PORT
1514 hidnplayr 984
	jz	.restart
1206 hidnplayr 985
 
1514 hidnplayr 986
	call	SOCKET_check_port
987
	jz	.findit
1206 hidnplayr 988
 
989
	ret
990
 
1257 hidnplayr 991
 
992
 
993
;-----------------------------------------------------------------
1206 hidnplayr 994
;
1542 hidnplayr 995
; SOCKET_check_port (to be used with AF_INET only!)
1206 hidnplayr 996
;
1514 hidnplayr 997
; Checks if a local port number is unused
998
; If the proposed port number is unused, it is filled in in the socket structure
1206 hidnplayr 999
;
1514 hidnplayr 1000
;  IN:  eax = socket ptr (to find out if its a TCP/UDP socket)
1001
;        bx = proposed socket number
1206 hidnplayr 1002
;
1514 hidnplayr 1003
;  OUT:  ZF = cleared on error
1004
;
1257 hidnplayr 1005
;-----------------------------------------------------------------
1206 hidnplayr 1006
align 4
1514 hidnplayr 1007
SOCKET_check_port:
1008
 
1536 hidnplayr 1009
	DEBUGF	1,"SOCKET_check_port\n"
1514 hidnplayr 1010
 
1542 hidnplayr 1011
	mov	ecx, [eax + SOCKET.Protocol]
1206 hidnplayr 1012
	mov	esi, net_sockets
1013
 
1014
  .next_socket:
1514 hidnplayr 1015
	mov	esi, [esi + SOCKET.NextPtr]
1206 hidnplayr 1016
	or	esi, esi
1017
	jz	.port_ok
1018
 
1542 hidnplayr 1019
	cmp	[esi + SOCKET.Protocol], ecx
1206 hidnplayr 1020
	jne	.next_socket
1021
 
1514 hidnplayr 1022
	cmp	[esi + UDP_SOCKET.LocalPort], bx
1206 hidnplayr 1023
	jne	.next_socket
1024
 
1514 hidnplayr 1025
	DEBUGF	1,"local port %u already in use\n", bx
1026
	ret
1206 hidnplayr 1027
 
1028
  .port_ok:
1514 hidnplayr 1029
	mov	[eax + UDP_SOCKET.LocalPort], bx
1030
	or	bx, bx					; set the zero-flag
1031
 
1206 hidnplayr 1032
	ret
1033
 
1034
 
1257 hidnplayr 1035
 
1036
;-----------------------------------------------------------------
1206 hidnplayr 1037
;
1514 hidnplayr 1038
; SOCKET_input
1206 hidnplayr 1039
;
1536 hidnplayr 1040
; Updates a (stateless) socket with received data
1206 hidnplayr 1041
;
1514 hidnplayr 1042
; Note: the mutex should already be set !
1206 hidnplayr 1043
;
1249 hidnplayr 1044
;  IN:  eax = socket ptr
1514 hidnplayr 1045
;       ebx = pointer to device struct
1046
;       ecx = data size
1047
;       esi = ptr to data
1048
;       [esp] = ptr to buf
1049
;       [esp + 4] = buf size
1249 hidnplayr 1050
;
1514 hidnplayr 1051
;  OUT: /
1206 hidnplayr 1052
;
1257 hidnplayr 1053
;-----------------------------------------------------------------
1206 hidnplayr 1054
align 4
1514 hidnplayr 1055
SOCKET_input:
1206 hidnplayr 1056
 
1536 hidnplayr 1057
	DEBUGF	1,"SOCKET_input: socket=%x, data=%x size=%u\n", eax, esi, ecx
1206 hidnplayr 1058
 
1514 hidnplayr 1059
	mov	dword[esp+4], ecx
1060
	push	esi
1249 hidnplayr 1061
	mov	esi, esp
1514 hidnplayr 1062
 
1536 hidnplayr 1063
	add_to_queue (eax + SOCKET_QUEUE_LOCATION), SOCKET_QUEUE_SIZE, socket_queue_entry.size, SOCKET_input.full
1514 hidnplayr 1064
 
1541 hidnplayr 1065
	DEBUGF	1,"SOCKET_input: queued packet successfully\n"
1257 hidnplayr 1066
	add	esp, socket_queue_entry.size
1514 hidnplayr 1067
	mov	[eax + SOCKET.lock], 0
1068
	jmp	SOCKET_notify_owner
1206 hidnplayr 1069
 
1514 hidnplayr 1070
  .full:
1541 hidnplayr 1071
	DEBUGF	2,"SOCKET_input: socket %x is full!\n", eax
1514 hidnplayr 1072
	mov	[eax + SOCKET.lock], 0
1073
	call	kernel_free
1074
	add	esp, 8
1206 hidnplayr 1075
 
1514 hidnplayr 1076
	ret
1077
 
1533 hidnplayr 1078
 
1079
;--------------------------
1080
;
1081
; eax = ptr to ring struct (just a buffer of the right size)
1082
;
1083
align 4
1084
SOCKET_ring_create:
1085
 
1543 hidnplayr 1086
	push	esi
1533 hidnplayr 1087
	mov	esi, eax
1543 hidnplayr 1088
 
1089
	push	edx
1533 hidnplayr 1090
	stdcall create_ring_buffer, SOCKET_MAXDATA, PG_SW
1543 hidnplayr 1091
	pop	edx
1533 hidnplayr 1092
 
1093
	DEBUGF	1,"SOCKET_ring_created: %x\n", eax
1094
	mov	[esi + RING_BUFFER.start_ptr], eax
1095
	mov	[esi + RING_BUFFER.write_ptr], eax
1096
	mov	[esi + RING_BUFFER.read_ptr], eax
1097
	mov	[esi + RING_BUFFER.size], 0
1098
	add	eax,  SOCKET_MAXDATA
1099
	mov	[esi + RING_BUFFER.end_ptr], eax
1543 hidnplayr 1100
	mov	eax, esi
1101
	pop	esi
1533 hidnplayr 1102
 
1103
	ret
1104
 
1514 hidnplayr 1105
;-----------------------------------------------------------------
1106
;
1533 hidnplayr 1107
; SOCKET_ring_write
1529 hidnplayr 1108
;
1533 hidnplayr 1109
; Adds data to a stream socket, and updates write pointer and size
1529 hidnplayr 1110
;
1111
;  IN:  eax = ptr to ring struct
1112
;       ecx = data size
1113
;       esi = ptr to data
1114
;
1533 hidnplayr 1115
;  OUT: ecx = number of bytes stored
1529 hidnplayr 1116
;
1117
;-----------------------------------------------------------------
1118
align 4
1533 hidnplayr 1119
SOCKET_ring_write:
1529 hidnplayr 1120
 
1533 hidnplayr 1121
	DEBUGF	1,"SOCKET_ring_write: ringbuff=%x ptr=%x size=%u\n", eax, esi, ecx
1529 hidnplayr 1122
 
1533 hidnplayr 1123
	add	[eax + RING_BUFFER.size], ecx
1124
	cmp	[eax + RING_BUFFER.size], SOCKET_MAXDATA
1529 hidnplayr 1125
	jg	.too_large
1126
 
1127
  .copy:
1533 hidnplayr 1128
	mov	edi, [eax + RING_BUFFER.write_ptr]
1541 hidnplayr 1129
	DEBUGF	2,"SOCKET_ring_write: %u bytes from %x to %x\n", ecx, esi, edi
1529 hidnplayr 1130
 
1131
	push	ecx
1533 hidnplayr 1132
	shr	ecx, 1
1133
	jnc	.nb
1134
	movsb
1536 hidnplayr 1135
  .nb:
1533 hidnplayr 1136
	shr	ecx, 1
1137
	jnc	.nw
1138
	movsw
1536 hidnplayr 1139
  .nw:
1533 hidnplayr 1140
	test	ecx, ecx
1141
	jz	.nd
1142
	rep	movsd
1536 hidnplayr 1143
  .nd:
1529 hidnplayr 1144
	pop	ecx
1145
 
1533 hidnplayr 1146
	cmp	edi, [eax + RING_BUFFER.end_ptr]
1147
	jge	.wrap
1148
	mov	[eax + RING_BUFFER.write_ptr], edi
1149
 
1529 hidnplayr 1150
	ret
1151
 
1533 hidnplayr 1152
  .wrap:
1153
	sub	edi, SOCKET_MAXDATA
1154
	mov	[eax + RING_BUFFER.write_ptr], edi
1155
 
1156
	ret
1157
 
1529 hidnplayr 1158
  .too_large:
1159
	mov	ecx, SOCKET_MAXDATA				; calculate number of bytes available in buffer
1160
	sub	ecx, [eax + RING_BUFFER.size]
1533 hidnplayr 1161
	jge	.full
1529 hidnplayr 1162
 
1163
	mov	[eax + RING_BUFFER.size], SOCKET_MAXDATA	; update size, we will fill buffer completely
1164
	jmp	.copy
1165
 
1166
  .full:
1541 hidnplayr 1167
	DEBUGF	2,"SOCKET_ring_write: ring buffer is full!\n"
1529 hidnplayr 1168
	xor	ecx, ecx
1169
	ret
1170
 
1171
 
1172
;-----------------------------------------------------------------
1173
;
1174
; SOCKET_ring_read
1175
;
1533 hidnplayr 1176
; reads the data, BUT DOES NOT CLEAR IT FROM MEMORY YET
1529 hidnplayr 1177
;
1178
;  IN:  eax = ptr to ring struct
1179
;       ecx = buffer size
1180
;       edi = ptr to buffer
1181
;
1533 hidnplayr 1182
;  OUT: ecx = number of bytes read
1529 hidnplayr 1183
;
1184
;-----------------------------------------------------------------
1185
align 4
1186
SOCKET_ring_read:
1187
 
1533 hidnplayr 1188
	DEBUGF	1,"SOCKET_ring_read: ringbuff=%x ptr=%x size=%u\n", eax, edi, ecx
1529 hidnplayr 1189
 
1533 hidnplayr 1190
	cmp	ecx, [eax + RING_BUFFER.size]
1191
	jg	.less_data
1529 hidnplayr 1192
 
1193
  .copy:
1533 hidnplayr 1194
	mov	esi, [eax + RING_BUFFER.read_ptr]
1529 hidnplayr 1195
 
1541 hidnplayr 1196
	DEBUGF	2,"SOCKET_ring_read: %u bytes from %x to %x\n", ecx, esi, edi
1529 hidnplayr 1197
	push	ecx
1533 hidnplayr 1198
	shr	ecx, 1
1199
	jnc	.nb
1200
	movsb
1536 hidnplayr 1201
  .nb:
1533 hidnplayr 1202
	shr	ecx, 1
1203
	jnc	.nw
1204
	movsw
1536 hidnplayr 1205
  .nw:
1533 hidnplayr 1206
	test	ecx, ecx
1207
	jz	.nd
1208
	rep	movsd
1536 hidnplayr 1209
  .nd:
1529 hidnplayr 1210
	pop	ecx
1211
 
1533 hidnplayr 1212
;  .no_data_at_all:
1529 hidnplayr 1213
	ret
1214
 
1533 hidnplayr 1215
  .less_data:
1529 hidnplayr 1216
	mov	ecx, [eax + RING_BUFFER.size]
1533 hidnplayr 1217
	test	ecx, ecx
1218
;        jz      .no_data_at_all
1529 hidnplayr 1219
	jmp	.copy
1220
 
1221
 
1222
;-----------------------------------------------------------------
1223
;
1224
; SOCKET_ring_free
1225
;
1226
; Free's some bytes from the ringbuffer
1227
;
1228
;  IN:  eax = ptr to ring struct
1229
;       ecx = data size
1230
;
1231
;  OUT: ecx = number of bytes free-ed
1232
;
1233
;-----------------------------------------------------------------
1234
align 4
1235
SOCKET_ring_free:
1236
 
1536 hidnplayr 1237
	DEBUGF	1,"SOCKET_ring_free: %u bytes from ring %x\n", ecx, eax
1529 hidnplayr 1238
 
1239
	sub	[eax + RING_BUFFER.size], ecx
1533 hidnplayr 1240
	jl	.sumthinwong
1529 hidnplayr 1241
	add	[eax + RING_BUFFER.read_ptr], ecx
1242
 
1243
	mov	edx, [eax + RING_BUFFER.end_ptr]
1244
	cmp	[eax + RING_BUFFER.read_ptr], edx
1245
	jl	@f
1533 hidnplayr 1246
	sub	[eax + RING_BUFFER.read_ptr], SOCKET_MAXDATA
1529 hidnplayr 1247
       @@:
1248
	ret
1249
 
1533 hidnplayr 1250
  .sumthinwong: 	       ; we could free all available bytes, but that would be stupid, i guess..
1251
	add	[eax + RING_BUFFER.size], ecx
1529 hidnplayr 1252
	xor	ecx, ecx
1253
	ret
1254
 
1255
 
1256
;-----------------------------------------------------------------
1257
;
1514 hidnplayr 1258
; SOCKET_notify_owner
1259
;
1260
; notify's the owner of a socket that something happened
1261
;
1262
;  IN:  eax = socket ptr
1263
;  OUT: /
1264
;
1265
;-----------------------------------------------------------------
1266
align 4
1267
SOCKET_notify_owner:
1268
 
1536 hidnplayr 1269
	DEBUGF	1,"SOCKET_notify_owner: %x\n", eax
1514 hidnplayr 1270
 
1271
	call	SOCKET_check
1272
	jz	.error
1273
 
1543 hidnplayr 1274
	push	eax ecx esi
1514 hidnplayr 1275
 
1276
; socket exists, now try to flag an event to the application
1277
 
1278
	mov	eax, [eax + SOCKET.PID]
1206 hidnplayr 1279
	mov	ecx, 1
1280
	mov	esi, TASK_DATA + TASKDATA.pid
1281
 
1282
       .next_pid:
1514 hidnplayr 1283
	cmp	[esi], eax
1206 hidnplayr 1284
	je	.found_pid
1285
	inc	ecx
1286
	add	esi, 0x20
1287
	cmp	ecx, [TASK_COUNT]
1288
	jbe	.next_pid
1289
 
1514 hidnplayr 1290
; PID not found, TODO: close socket!
1291
 
1292
	jmp	.error2
1293
 
1206 hidnplayr 1294
       .found_pid:
1295
	shl	ecx, 8
1514 hidnplayr 1296
	or	[ecx + SLOT_BASE + APPDATA.event_mask], EVENT_NETWORK
1206 hidnplayr 1297
	mov	[check_idle_semaphore], 200
1298
 
1536 hidnplayr 1299
	DEBUGF	1,"SOCKET_notify_owner: succes!\n"
1514 hidnplayr 1300
 
1301
  .error2:
1543 hidnplayr 1302
	pop	esi ecx eax
1536 hidnplayr 1303
 
1514 hidnplayr 1304
  .error:
1305
 
1206 hidnplayr 1306
	ret
1307
 
1308
 
1514 hidnplayr 1309
;--------------------------------------------------------------------
1310
;
1311
; SOCKET_alloc
1312
;
1159 hidnplayr 1313
; Allocate memory for socket data and put new socket into the list
1314
; Newly created socket is initialized with calling PID and number and
1315
; put into beginning of list (which is a fastest way).
1316
;
1514 hidnplayr 1317
; IN:  /
1318
; OUT: eax = 0 on error, socket ptr otherwise
1319
;      edi = socket number
1320
;       ZF = cleared on error
1159 hidnplayr 1321
;
1514 hidnplayr 1322
;--------------------------------------------------------------------
1323
align 4
1324
SOCKET_alloc:
1325
 
1326
	push	ecx ebx
1327
 
1159 hidnplayr 1328
	stdcall kernel_alloc, SOCKETBUFFSIZE
1529 hidnplayr 1329
	DEBUGF	1, "SOCKET_alloc: ptr=%x\n", eax
1159 hidnplayr 1330
	or	eax, eax
1331
	jz	.exit
1332
 
1514 hidnplayr 1333
; zero-initialize allocated memory
1334
	push	eax edi
1159 hidnplayr 1335
	mov	edi, eax
1336
	mov	ecx, SOCKETBUFFSIZE / 4
1337
	xor	eax, eax
1338
	rep	stosd
1514 hidnplayr 1339
	pop	edi eax
1159 hidnplayr 1340
 
1536 hidnplayr 1341
; set send-and receive procedures to return -1
1342
	mov	[eax + SOCKET.snd_proc], s_error
1343
	mov	[eax + SOCKET.rcv_proc], s_error
1344
 
1514 hidnplayr 1345
; find first free socket number and use it
1543 hidnplayr 1346
	mov	ecx, [last_socket_num]
1159 hidnplayr 1347
  .next_socket_number:
1348
	inc	ecx
1543 hidnplayr 1349
	jz	.next_socket_number	; avoid socket nr 0
1350
	cmp	ecx, -1
1351
	je	.next_socket_number	; avoid socket nr -1
1536 hidnplayr 1352
	mov	ebx, net_sockets
1159 hidnplayr 1353
  .next_socket:
1514 hidnplayr 1354
	mov	ebx, [ebx + SOCKET.NextPtr]
1529 hidnplayr 1355
	test	ebx, ebx
1514 hidnplayr 1356
	jz	.last_socket
1536 hidnplayr 1357
 
1514 hidnplayr 1358
	cmp	[ebx + SOCKET.Number], ecx
1159 hidnplayr 1359
	jne	.next_socket
1360
	jmp	.next_socket_number
1361
 
1514 hidnplayr 1362
  .last_socket:
1543 hidnplayr 1363
	mov	[last_socket_num], ecx
1514 hidnplayr 1364
	mov	[eax + SOCKET.Number], ecx
1529 hidnplayr 1365
	DEBUGF	1, "SOCKET_alloc: number=%u\n", ecx
1366
	mov	edi, ecx
1159 hidnplayr 1367
 
1514 hidnplayr 1368
; Fill in PID
1369
	mov	ebx, [TASK_BASE]
1370
	mov	ebx, [ebx + TASKDATA.pid]
1371
	mov	[eax + SOCKET.PID], ebx
1372
 
1529 hidnplayr 1373
; add socket to the list by re-arranging some pointers
1514 hidnplayr 1374
	mov	ebx, [net_sockets + SOCKET.NextPtr]
1375
 
1376
	mov	[eax + SOCKET.PrevPtr], net_sockets
1377
	mov	[eax + SOCKET.NextPtr], ebx
1378
 
1529 hidnplayr 1379
	test	ebx, ebx
1514 hidnplayr 1380
	jz	@f
1381
	add	ebx, SOCKET.lock	; lock the next socket
1382
	call	wait_mutex
1383
	sub	ebx, SOCKET.lock
1384
	mov	[ebx + SOCKET.PrevPtr], eax
1536 hidnplayr 1385
	mov	[ebx + SOCKET.lock], 0	; and unlock it again
1514 hidnplayr 1386
       @@:
1387
 
1388
	mov	[net_sockets + SOCKET.NextPtr], eax
1529 hidnplayr 1389
	or	eax, eax		; used to clear zero flag
1159 hidnplayr 1390
  .exit:
1514 hidnplayr 1391
	pop	ebx ecx
1392
 
1159 hidnplayr 1393
	ret
1394
 
1514 hidnplayr 1395
 
1396
;----------------------------------------------------
1159 hidnplayr 1397
;
1514 hidnplayr 1398
; SOCKET_free
1159 hidnplayr 1399
;
1514 hidnplayr 1400
; Free socket data memory and remove socket from the list
1401
;
1402
; IN:  eax = socket ptr
1403
; OUT: /
1404
;
1405
;----------------------------------------------------
1406
align 4
1407
SOCKET_free:
1159 hidnplayr 1408
 
1536 hidnplayr 1409
	DEBUGF	1, "SOCKET_free: %x\n", eax
1514 hidnplayr 1410
 
1411
	call	SOCKET_check
1159 hidnplayr 1412
	jz	.error
1413
 
1514 hidnplayr 1414
	push	ebx
1415
	lea	ebx, [eax + SOCKET.lock]
1416
	call	wait_mutex
1417
 
1541 hidnplayr 1418
	DEBUGF	1, "SOCKET_free: freeing socket..\n"
1514 hidnplayr 1419
 
1529 hidnplayr 1420
	cmp	[eax + SOCKET.Domain], AF_INET4
1536 hidnplayr 1421
	jnz	.no_tcp
1529 hidnplayr 1422
 
1542 hidnplayr 1423
	cmp	[eax + SOCKET.Protocol], IP_PROTO_TCP
1536 hidnplayr 1424
	jnz	.no_tcp
1529 hidnplayr 1425
 
1536 hidnplayr 1426
	mov	ebx, eax
1427
	stdcall kernel_free, [ebx + STREAM_SOCKET.rcv + RING_BUFFER.start_ptr]
1428
	stdcall kernel_free, [ebx + STREAM_SOCKET.snd + RING_BUFFER.start_ptr]
1429
	mov	eax, ebx
1430
  .no_tcp:
1529 hidnplayr 1431
 
1514 hidnplayr 1432
	push	eax				; this will be passed to kernel_free
1433
	mov	ebx, [eax + SOCKET.NextPtr]
1434
	mov	eax, [eax + SOCKET.PrevPtr]
1435
 
1541 hidnplayr 1436
	DEBUGF	1, "SOCKET_free: linking socket %x to socket %x\n", eax, ebx
1514 hidnplayr 1437
 
1438
	test	eax, eax
1159 hidnplayr 1439
	jz	@f
1514 hidnplayr 1440
	mov	[eax + SOCKET.NextPtr], ebx
1441
       @@:
1159 hidnplayr 1442
 
1514 hidnplayr 1443
	test	ebx, ebx
1444
	jz	@f
1445
	mov	[ebx + SOCKET.PrevPtr], eax
1446
       @@:
1249 hidnplayr 1447
 
1514 hidnplayr 1448
	call	kernel_free
1449
	pop	ebx
1159 hidnplayr 1450
 
1541 hidnplayr 1451
	DEBUGF	1, "SOCKET_free: success!\n"
1514 hidnplayr 1452
 
1159 hidnplayr 1453
  .error:
1454
	ret
1455
 
1543 hidnplayr 1456
;------------------------------------
1457
;
1458
; SOCKET_fork
1459
;
1460
; Create a child socket
1461
;
1533 hidnplayr 1462
; IN:  socket nr in ebx
1543 hidnplayr 1463
; OUT: child socket nr in eax
1464
;
1465
;-----------------------------------
1529 hidnplayr 1466
align 4
1467
SOCKET_fork:
1468
 
1543 hidnplayr 1469
	DEBUGF	1,"SOCKET_fork: %x\n", ebx
1529 hidnplayr 1470
 
1543 hidnplayr 1471
; Exit if backlog queue is full
1472
	mov	eax, [ebx + SOCKET_QUEUE_LOCATION + queue.size]
1473
	cmp	ax, [ebx + SOCKET.backlog]
1474
	jge	.fail
1475
 
1529 hidnplayr 1476
; Allocate new socket
1477
	call	SOCKET_alloc
1543 hidnplayr 1478
	jz	.fail
1529 hidnplayr 1479
 
1543 hidnplayr 1480
	push	esi ecx edi
1481
	push	eax
1482
	mov	esi, esp
1483
	add_to_queue (ebx + SOCKET_QUEUE_LOCATION), MAX_backlog, 4, .fail2
1484
	pop	eax
1485
 
1486
; Copy structure from current socket to new
1487
; We start at PID to preserve the socket num, and the 2 pointers at beginning of socket
1488
	lea	esi, [ebx + SOCKET.PID]
1529 hidnplayr 1489
	lea	edi, [eax + SOCKET.PID]
1543 hidnplayr 1490
	mov	ecx, (SOCKET_QUEUE_LOCATION - SOCKET.PID + 3)/4
1529 hidnplayr 1491
	rep	movsd
1492
 
1543 hidnplayr 1493
	and	[eax + SOCKET.options], not SO_ACCEPTCON
1529 hidnplayr 1494
 
1543 hidnplayr 1495
	call	SOCKET_notify_owner
1496
	pop	edi ecx esi
1529 hidnplayr 1497
 
1498
	ret
1499
 
1543 hidnplayr 1500
  .fail2:
1501
	add	esp, 4+4+4
1502
  .fail:
1503
	DEBUGF	1,"SOCKET_fork: failed\n"
1504
	xor	eax, eax
1505
	ret
1529 hidnplayr 1506
 
1543 hidnplayr 1507
 
1514 hidnplayr 1508
;---------------------------------------------------
1509
;
1510
; SOCKET_num_to_ptr
1511
;
1159 hidnplayr 1512
; Get socket structure address by its number
1513
;
1514 hidnplayr 1514
; IN:  ecx = socket number
1533 hidnplayr 1515
; OUT: eax = 0 on error, socket ptr otherwise
1514 hidnplayr 1516
;       ZF = set on error
1159 hidnplayr 1517
;
1514 hidnplayr 1518
;---------------------------------------------------
1519
align 4
1520
SOCKET_num_to_ptr:
1159 hidnplayr 1521
 
1536 hidnplayr 1522
	DEBUGF	1,"SOCKET_num_to_ptr: %u ", ecx
1514 hidnplayr 1523
 
1524
	mov	eax, net_sockets
1525
 
1159 hidnplayr 1526
  .next_socket:
1514 hidnplayr 1527
	mov	eax, [eax + SOCKET.NextPtr]
1528
	or	eax, eax
1159 hidnplayr 1529
	jz	.error
1514 hidnplayr 1530
	cmp	[eax + SOCKET.Number], ecx
1159 hidnplayr 1531
	jne	.next_socket
1532
 
1514 hidnplayr 1533
	test	eax, eax
1159 hidnplayr 1534
 
1514 hidnplayr 1535
	DEBUGF	1,"(%x)\n", eax
1159 hidnplayr 1536
  .error:
1537
	ret
1538
 
1514 hidnplayr 1539
 
1540
;---------------------------------------------------
1159 hidnplayr 1541
;
1514 hidnplayr 1542
; SOCKET_ptr_to_num
1159 hidnplayr 1543
;
1514 hidnplayr 1544
; Get socket number by its address
1545
;
1546
; IN:  eax = socket ptr
1547
; OUT: eax = 0 on error, socket num otherwise
1548
;       ZF = set on error
1549
;
1550
;---------------------------------------------------
1551
align 4
1552
SOCKET_ptr_to_num:
1553
 
1536 hidnplayr 1554
	DEBUGF	1,"SOCKET_ptr_to_num: %x ", eax
1514 hidnplayr 1555
 
1556
	call	SOCKET_check
1159 hidnplayr 1557
	jz	.error
1558
 
1514 hidnplayr 1559
	mov	eax, [eax + SOCKET.Number]
1560
 
1561
	DEBUGF	1,"(%u)\n", eax
1562
 
1563
  .error:
1564
	ret
1565
 
1566
 
1567
;---------------------------------------------------
1568
;
1569
; SOCKET_check
1570
;
1571
; checks if the given value is really a socket ptr
1572
;
1573
; IN:  eax = socket ptr
1574
; OUT: eax = 0 on error, unchanged otherwise
1575
;       ZF = set on error
1576
;
1577
;---------------------------------------------------
1578
align 4
1579
SOCKET_check:
1580
 
1536 hidnplayr 1581
	DEBUGF	1,"SOCKET_check: %x\n", eax
1514 hidnplayr 1582
 
1583
	push	ebx
1159 hidnplayr 1584
	mov	ebx, net_sockets
1514 hidnplayr 1585
 
1159 hidnplayr 1586
  .next_socket:
1514 hidnplayr 1587
	mov	ebx, [ebx + SOCKET.NextPtr]
1159 hidnplayr 1588
	or	ebx, ebx
1514 hidnplayr 1589
	jz	.done
1159 hidnplayr 1590
	cmp	ebx, eax
1514 hidnplayr 1591
	jnz	.next_socket
1159 hidnplayr 1592
 
1514 hidnplayr 1593
  .done:
1594
	mov	eax, ebx
1595
	test	eax, eax
1596
	pop	ebx
1597
 
1159 hidnplayr 1598
	ret
1599
 
1514 hidnplayr 1600
 
1601
 
1602
;---------------------------------------------------
1603
;
1604
; SOCKET_check_owner
1605
;
1606
; checks if the caller application owns the socket
1607
;
1608
; IN:  eax = socket ptr
1609
; OUT:  ZF = true/false
1610
;
1611
;---------------------------------------------------
1612
align 4
1613
SOCKET_check_owner:
1614
 
1536 hidnplayr 1615
	DEBUGF	1,"SOCKET_check_owner: %x\n", eax
1514 hidnplayr 1616
 
1617
	push	ebx
1618
	mov	ebx, [TASK_BASE]
1619
	mov	ebx, [ecx + TASKDATA.pid]
1620
	cmp	[eax + SOCKET.PID], ebx
1621
	pop	 ebx
1622
 
1159 hidnplayr 1623
	ret
1514 hidnplayr 1624
 
1625
 
1626
 
1627
 
1628
;---------------------------------------------------
1629
;
1630
; SOCKET_process_end
1631
;
1632
; Kernel calls this function when a certain process ends
1633
; This function will check if the process had any open sockets
1634
; And update them accordingly
1635
;
1636
; IN:  eax = pid
1637
; OUT: /
1638
;
1639
;------------------------------------------------------
1640
align 4
1641
SOCKET_process_end:
1642
 
1536 hidnplayr 1643
	DEBUGF	1,"SOCKET_process_end: %x\n", eax
1514 hidnplayr 1644
 
1645
	push	ebx
1646
	mov	ebx, net_sockets
1647
 
1648
  .next_socket:
1649
 
1650
	mov	ebx, [ebx + SOCKET.NextPtr]
1651
  .test_socket:
1652
	test	ebx, ebx
1653
	jz	.done
1654
 
1655
	cmp	[ebx + SOCKET.PID], eax
1656
	jne	.next_socket
1657
 
1658
	DEBUGF	1,"closing socket %x", eax, ebx
1659
 
1660
	mov	[ebx + SOCKET.PID], 0
1661
 
1542 hidnplayr 1662
	cmp	[ebx + SOCKET.Protocol], IP_PROTO_UDP
1514 hidnplayr 1663
	je	.udp
1664
 
1542 hidnplayr 1665
	cmp	[ebx + SOCKET.Protocol], IP_PROTO_TCP
1514 hidnplayr 1666
	je	.tcp
1667
 
1668
	jmp	.next_socket	; kill all sockets for given PID
1669
 
1670
  .udp:
1671
	mov	eax, ebx
1672
	mov	ebx, [ebx + SOCKET.NextPtr]
1673
	call	SOCKET_free
1674
	jmp	.test_socket
1675
 
1676
  .tcp:
1677
 
1678
	jmp	.next_socket
1679
 
1680
  .done:
1681
	pop	ebx
1682
 
1683
	ret
1773 hidnplayr 1684
 
1685
 
1686
 
1687
 
1688
 
1689
 
1690
 
1691
 
1692
;-----------------------------------------------------------------
1693
;
1694
; SOCKET_is_disconnecting
1695
;
1696
;  IN:  eax = socket ptr
1697
;  OUT: /
1698
;
1699
;-----------------------------------------------------------------
1700
 
1701
align 4
1702
SOCKET_is_disconnecting:
1703
 
1704
	and	[eax + SOCKET.options], not (SS_ISCONNECTING)
1705
	or	[eax + SOCKET.options], SS_ISDISCONNECTING + SS_CANTRCVMORE + SS_CANTSENDMORE
1706
 
1707
	jmp	SOCKET_notify_owner
1708
 
1709
 
1710
 
1711
;-----------------------------------------------------------------
1712
;
1713
; SOCKET_is_disconnected
1714
;
1715
;  IN:  eax = socket ptr
1716
;  OUT: /
1717
;
1718
;-----------------------------------------------------------------
1719
 
1720
align 4
1721
SOCKET_is_disconnected:
1722
 
1723
	and	[eax + SOCKET.options], not (SS_ISCONNECTING + SS_ISCONNECTED + SS_ISDISCONNECTING)
1724
	or	[eax + SOCKET.options], SS_CANTRCVMORE + SS_CANTSENDMORE
1725
 
1726
	jmp	SOCKET_notify_owner