Subversion Repositories Kolibri OS

Rev

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