Subversion Repositories Kolibri OS

Rev

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