Subversion Repositories Kolibri OS

Rev

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