Subversion Repositories Kolibri OS

Rev

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