Subversion Repositories Kolibri OS

Rev

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