Subversion Repositories Kolibri OS

Rev

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