Subversion Repositories Kolibri OS

Rev

Details | Last modification | View Log | RSS feed

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