Subversion Repositories Kolibri OS

Rev

Rev 1208 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
1159 hidnplayr 1
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2
;;                                                                 ;;
1196 hidnplayr 3
;; Copyright (C) KolibriOS team 2004-2009. All rights reserved.    ;;
1159 hidnplayr 4
;; Distributed under terms of the GNU General Public License       ;;
5
;;                                                                 ;;
6
;;  SOCKET.INC                                                     ;;
7
;;                                                                 ;;
8
;;    Written by hidnplayr@kolibrios.org                           ;;
9
;;    based on code by mike.dld                                    ;;
10
;;                                                                 ;;
11
;;          GNU GENERAL PUBLIC LICENSE                             ;;
12
;;             Version 2, June 1991                                ;;
13
;;                                                                 ;;
14
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
15
 
1206 hidnplayr 16
$Revision: 1249 $
1159 hidnplayr 17
 
1249 hidnplayr 18
struct	SOCKET_head
1159 hidnplayr 19
	 .PrevPtr		dd ? ; pointer to previous socket in list
20
	 .NextPtr		dd ? ; pointer to next socket in list
21
	 .Number		dd ? ; socket number (unique within single process)
22
	 .PID			dd ? ; application process id
23
	 .Domain		dd ? ; INET/UNIX/..
24
	 .Type			dd ? ; RAW/UDP/TCP/...
1196 hidnplayr 25
	 .Protocol		dd ? ; ICMP/IPv4/ARP/
1249 hidnplayr 26
	 .lock			dd ? ; lock mutex
27
	 .end:
28
ends
29
 
30
struct	IPv4_SOCKET
31
	 .LocalIP		dd ?
32
	 .RemoteIP		dd ?
33
	 .SequenceNumber	dd ?
34
 
35
	; todo: add options (for func 8 and 9)
36
 
37
	 .end:
38
ends
39
 
40
struct	TCP_SOCKET
41
 
42
	 .LocalPort		dw ? ; In INET byte order
43
	 .RemotePort		dw ? ; In INET byte order
44
 
45
	 .backlog		dw ? ; Backlog
1196 hidnplayr 46
	 .OrigRemoteIP		dd ? ; original remote IP address (used to reset to LISTEN state)
47
	 .OrigRemotePort	dw ? ; original remote port (used to reset to LISTEN state)
48
	 .TCBState		dd ? ; TCB state
49
	 .TCBTimer		dd ? ; TCB timer (seconds)
50
	 .ISS			dd ? ; initial send sequence
51
	 .IRS			dd ? ; initial receive sequence
52
	 .SND_UNA		dd ? ; sequence number of unack'ed sent Packets
1249 hidnplayr 53
	 .SND_NXT		dd ? ; next send sequence number to use
1196 hidnplayr 54
	 .SND_WND		dd ? ; send window
55
	 .RCV_NXT		dd ? ; next receive sequence number to use
56
	 .RCV_WND		dd ? ; receive window
57
	 .SEG_LEN		dd ? ; segment length
58
	 .SEG_WND		dd ? ; segment window
1159 hidnplayr 59
	 .wndsizeTimer		dd ? ; window size timer
1249 hidnplayr 60
 
61
	 .flags 		db ? ; packet flags
62
 
63
	 .end:
1159 hidnplayr 64
ends
65
 
1249 hidnplayr 66
struct	UDP_SOCKET
1159 hidnplayr 67
 
1249 hidnplayr 68
	 .LocalPort		dw ? ; In INET byte order
69
	 .RemotePort		dw ? ; In INET byte order
1159 hidnplayr 70
 
1249 hidnplayr 71
	 .end:
72
ends
73
 
74
struct	ICMP_SOCKET
75
 
76
	.Identifier		dw ? ;
77
 
78
	.end:
79
 
80
ends
81
 
82
struct	IPC_SOCKET
83
 
84
	.ConnectedTo		dd ? ; Socket number of other socket this one is connected to
85
 
86
	.end:
87
 
88
ends
89
 
90
MAX_backlog		equ 20	     ; backlog for stream sockets
91
SOCKETBUFFSIZE		equ 4096     ; in bytes
92
SOCKET_QUEUE_SIZE	equ 10	     ; maximum number ofincoming packets queued for 1 socket
93
 
1159 hidnplayr 94
uglobal
95
	net_sockets	rd 2
96
	last_UDP_port	dw ? ; These values give the number of the last used ephemeral port
97
	last_TCP_port	dw ? ;
98
endg
99
 
100
 
101
;-----------------------------------------------
102
;
103
; SOCKET_init
104
;
105
;  -
106
;
107
;  IN:  /
108
;  OUT: /
109
;
110
;-----------------------------------------------
111
 
112
align 4
113
socket_init:
114
 
115
	mov	[net_sockets], 0
116
	mov	[net_sockets + 4], 0
117
 
118
	mov	[last_UDP_port], MIN_EPHEMERAL_PORT
119
	mov	[last_TCP_port], MIN_EPHEMERAL_PORT
120
 
121
	ret
122
 
123
 
124
;-----------------------------------------------------------------------------
125
;
126
; Socket API (function 74)
127
;
128
;-----------------------------------------------------------------------------
129
 
130
align 4
131
sys_socket:
132
 
133
	test	bl, bl
134
	jz	socket_open	; 0
135
	dec	bl
136
	jz	socket_close	; 1
137
	dec	bl
138
	jz	socket_bind	; 2
139
	dec	bl
140
	jz	socket_listen	; 3
141
	dec	bl
142
	jz	socket_connect	; 4
143
	dec	bl
144
	jz	socket_accept	; 5
145
	dec	bl
146
	jz	socket_send	; 6
147
	dec	bl
148
	jz	socket_recv	; 7
1249 hidnplayr 149
	dec	bl
150
;        jz      socket_get_opt  ; 8
151
	dec	bl
152
;        jz      socket_set_opt  ; 9
1159 hidnplayr 153
 
1185 hidnplayr 154
s_error:
1159 hidnplayr 155
	mov	dword [esp+32],-1
156
 
157
	ret
158
 
159
 
160
 
161
 
162
;-----------------------------------------------
163
;
164
; SOCKET_open
165
;
166
;
167
;  IN:  domain in ecx
168
;       type in edx
1196 hidnplayr 169
;       protocol in esi
1159 hidnplayr 170
;  OUT: eax is socket num, -1 on error
171
;
172
;-----------------------------------------------
1206 hidnplayr 173
align 4
1159 hidnplayr 174
socket_open:
175
 
176
	DEBUGF	1,"socket_open: domain: %u, type: %u",ecx, edx
177
 
178
	call	net_socket_alloc
179
	or	eax, eax
1185 hidnplayr 180
	jz	s_error
1159 hidnplayr 181
 
1249 hidnplayr 182
	mov	[eax + SOCKET_head.Domain], ecx
183
	mov	[eax + SOCKET_head.Type], edx
184
	mov	[eax + SOCKET_head.Protocol], esi
1159 hidnplayr 185
 
186
	stdcall net_socket_addr_to_num, eax
187
	DEBUGF	1,", socketnumber: %u\n", eax
188
 
189
	mov	[esp+32], eax
190
 
191
	ret
192
 
193
 
194
 
195
 
1249 hidnplayr 196
 
197
 
198
 
199
 
1159 hidnplayr 200
;-----------------------------------------------
201
;
202
; SOCKET_bind
203
;
204
;  IN:  socket number in ecx
205
;       pointer to sockaddr struct in edx
206
;       length of that struct in esi
207
;  OUT: 0 on success
208
;
209
;-----------------------------------------------
1206 hidnplayr 210
align 4
1159 hidnplayr 211
socket_bind:
212
 
213
	DEBUGF	1,"Socket_bind: socknum: %u sockaddr: %x, length: %u, ",ecx,edx,esi
214
 
215
	stdcall net_socket_num_to_addr, ecx
216
	cmp	eax, -1
1185 hidnplayr 217
	jz	s_error
1159 hidnplayr 218
 
219
	cmp	esi, 2
1185 hidnplayr 220
	jl	s_error
1159 hidnplayr 221
 
222
	cmp	word [edx], AF_INET4
1249 hidnplayr 223
	je	.af_inet4
1159 hidnplayr 224
 
1249 hidnplayr 225
	cmp	word [edx], AF_UNIX
226
	je	.af_unix
227
 
228
	jmp	s_error
229
 
230
  .af_unix:
231
 
232
	; TODO: write code here
233
 
234
 
235
	mov	dword [esp+32],0
236
	ret
237
 
1159 hidnplayr 238
  .af_inet4:
239
 
240
	cmp	esi, 6
1185 hidnplayr 241
	jl	s_error
1159 hidnplayr 242
 
1249 hidnplayr 243
	mov	ecx, [eax + SOCKET_head.Type]
244
 
1159 hidnplayr 245
	mov	bx, word [edx + 2]
1206 hidnplayr 246
	DEBUGF	1,"local port: %x ",bx
1159 hidnplayr 247
	test	bx, bx
1206 hidnplayr 248
	jz	.find_free
1159 hidnplayr 249
 
1206 hidnplayr 250
	call	socket_check_port
251
	test	bx, bx
252
	je	s_error
253
	jmp	.got_port
1159 hidnplayr 254
 
1249 hidnplayr 255
    .find_free:
1159 hidnplayr 256
 
1206 hidnplayr 257
	call	socket_find_port
258
	test	bx, bx
259
	je	s_error
1159 hidnplayr 260
 
1249 hidnplayr 261
    .got_port:
1206 hidnplayr 262
	DEBUGF	1,"using port: %x ",bx
1249 hidnplayr 263
	mov	word [eax + SOCKET_head.end + IPv4_SOCKET.end + UDP_SOCKET.LocalPort], bx
1159 hidnplayr 264
 
265
	mov	ebx, dword [edx + 4]
1249 hidnplayr 266
	mov	dword [eax + SOCKET_head.end + IPv4_SOCKET.LocalIP], ebx
1159 hidnplayr 267
 
268
	DEBUGF	1,"local ip: %u.%u.%u.%u\n",\
1249 hidnplayr 269
	[eax + SOCKET_head.end + IPv4_SOCKET.LocalIP + 0]:1,[eax + SOCKET_head.end + IPv4_SOCKET.LocalIP + 1]:1,\
270
	[eax + SOCKET_head.end + IPv4_SOCKET.LocalIP + 2]:1,[eax + SOCKET_head.end + IPv4_SOCKET.LocalIP + 3]:1
1159 hidnplayr 271
 
272
	mov	dword [esp+32],0
273
	ret
274
 
275
 
276
 
277
 
278
;-----------------------------------------------
279
;
280
; SOCKET_connect
281
;
282
;
283
;  IN:  socket number in ecx
284
;       pointer to sockaddr struct in edx
285
;       length of that struct in esi
286
;  OUT: 0 on success
287
;
288
;-----------------------------------------------
289
align 4
290
socket_connect:
291
 
292
	DEBUGF	1,"Socket_connect: socknum: %u sockaddr: %x, length: %u,",ecx,edx,esi
293
 
294
	stdcall net_socket_num_to_addr, ecx
295
	cmp	eax, -1
1185 hidnplayr 296
	jz	s_error
1159 hidnplayr 297
 
298
	cmp	esi, 2
1185 hidnplayr 299
	jl	s_error
1159 hidnplayr 300
 
301
	cmp	word [edx], AF_INET4
302
	je	.af_inet4
303
 
1185 hidnplayr 304
	jmp	s_error
1159 hidnplayr 305
 
306
  .af_inet4:
307
 
308
	cmp	esi, 8
1185 hidnplayr 309
	jl	s_error
1159 hidnplayr 310
 
1249 hidnplayr 311
	cmp	[eax + SOCKET_head.Type], IP_PROTO_UDP
1159 hidnplayr 312
	je	.udp
313
 
1249 hidnplayr 314
	cmp	[eax + SOCKET_head.Type], IP_PROTO_ICMP
1159 hidnplayr 315
	je	.icmp
316
 
1249 hidnplayr 317
	cmp	[eax + SOCKET_head.Type], IP_PROTO_TCP
1206 hidnplayr 318
	je	.tcp
1159 hidnplayr 319
 
1185 hidnplayr 320
	jmp	s_error
1159 hidnplayr 321
 
1249 hidnplayr 322
    .udp:
1159 hidnplayr 323
 
324
	mov	bx , word [edx + 2]
1249 hidnplayr 325
	mov	word [eax + SOCKET_head.end + IPv4_SOCKET.end + UDP_SOCKET.RemotePort], bx
1206 hidnplayr 326
	DEBUGF	1,"remote port: %x ",bx
1159 hidnplayr 327
 
328
	mov	ebx, dword [edx + 4]
1249 hidnplayr 329
	mov	dword [eax + SOCKET_head.end + IPv4_SOCKET.RemoteIP], ebx
1159 hidnplayr 330
	DEBUGF	1,"remote ip: %u.%u.%u.%u\n",[edx+4]:1,[edx+5]:1,[edx+6]:1,[edx+7]:1
331
 
332
	mov	dword [esp+32],0
333
	ret
334
 
1249 hidnplayr 335
    .icmp:
1159 hidnplayr 336
 
1249 hidnplayr 337
	; TODO: write code here
1159 hidnplayr 338
 
339
	ret
340
 
341
 
342
 
343
  .tcp:
344
 
345
;local sockAddr dd ?
346
 
347
;        cmp     esi, SOCKET_PASSIVE
348
;        jne     .skip_port_check
349
;
350
;        push    ebx
351
;        mov     eax, ebx
352
;        xchg    al, ah
353
;        mov     ebx, net_sockets
354
;
355
;  .next_socket:
356
;        mov     ebx, [ebx + SOCKET.NextPtr]
357
;        or      ebx, ebx
358
;        jz      .last_socket
359
;        cmp     [ebx + SOCKET.TCBState], TCB_LISTEN
360
;        jne     .next_socket
361
;        cmp     [ebx + SOCKET.LocalPort], ax
362
;        jne     .next_socket
363
;
364
;        xchg    al, ah
365
;        DEBUGF  1, "K : error: port %u is listened by 0x%x\n", ax, ebx
366
;        pop     ebx
367
;        jmp     .error
368
;
369
;  .last_socket:
370
;        pop     ebx
371
;
372
;  .skip_port_check:
373
 
374
;        mov     [eax + SOCKET.wndsizeTimer], 0     ; Reset the window timer.
375
;
376
;        xchg    bh, bl
377
;        mov     [eax + SOCKET.LocalPort], bx
378
;        xchg    ch, cl
379
;        mov     [eax + SOCKET.RemotePort], cx
380
;        mov     [eax + SOCKET.OrigRemotePort], cx
381
;        mov     ebx, [IP_LIST]
382
;        mov     [eax + SOCKET.LocalIP], ebx
383
;        mov     [eax + SOCKET.RemoteIP], edx
384
;        mov     [eax + SOCKET.OrigRemoteIP], edx
385
 
386
;        mov     ebx, TCB_LISTEN
387
;        cmp     esi, SOCKET_PASSIVE
388
;        je      @f
389
;        mov     ebx, TCB_SYN_SENT
390
;    @@: mov     [eax + SOCKET.TCBState], ebx            ; Indicate the state of the TCB
391
 
392
;        cmp     ebx, TCB_LISTEN
393
;        je      .exit
394
 
395
	; Now, if we are in active mode, then we have to send a SYN to the specified remote port
396
;        mov     eax, EMPTY_QUEUE
397
;        call    dequeue
398
;        cmp     ax, NO_BUFFER
399
;        je      .exit
400
 
401
;        push    eax
402
 
403
;        mov     bl, TH_SYN
404
;        xor     ecx, ecx
405
;        stdcall build_tcp_Packet, [sockAddr]
406
 
407
;        mov     eax, NET1OUT_QUEUE
408
;        mov     edx, [IP_LIST]
409
;        mov     ecx, [sockAddr]
410
;        cmp     edx, [ecx + SOCKET.RemoteIP]
411
;        jne     .not_local
412
;        mov     eax, IPIN_QUEUE
413
 
414
;  .not_local:
415
	; Send it.
416
;        pop     ebx
417
;        call    queue
418
 
419
  .exit:
420
	xor	eax, eax
421
	ret
422
 
423
 
424
 
425
 
426
;-----------------------------------------------
427
;
428
; SOCKET_listen
429
;
430
;
431
;  IN:  socket number in ecx
432
;       backlog in edx
433
;  OUT: eax is socket num, -1 on error
434
;
435
;-----------------------------------------------
1206 hidnplayr 436
align 4
1159 hidnplayr 437
socket_listen:
438
 
439
	DEBUGF	1,"Socket_listen: socknum: %u backlog: %u\n",ecx,edx
440
 
441
	stdcall net_socket_num_to_addr, ecx
442
	cmp	eax, -1
1185 hidnplayr 443
	jz	s_error
1159 hidnplayr 444
 
445
	cmp	edx, MAX_backlog
446
	jl	.ok
447
	mov	dx , 20
448
  .ok:
449
 
1249 hidnplayr 450
	mov	[eax + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.backlog], dx
1159 hidnplayr 451
 
452
	; TODO: insert code for active connections like TCP
453
 
454
	mov	dword [esp+32], 0
455
	ret
456
 
457
 
458
 
459
 
460
 
461
 
462
;-----------------------------------------------
463
;
464
; SOCKET_accept
465
;
466
;
467
;  IN:  socket number in ecx
468
;       addr in edx
469
;       addrlen in esi
470
;  OUT: eax is socket num, -1 on error
471
;
472
;-----------------------------------------------
1206 hidnplayr 473
align 4
1159 hidnplayr 474
socket_accept:
475
 
476
	DEBUGF	1,"Socket_accept: socknum: %u sockaddr: %x, length: %u\n",ecx,edx,esi
477
 
478
	stdcall net_socket_num_to_addr, ecx
479
	or	eax, eax
1185 hidnplayr 480
	jz	s_error
1159 hidnplayr 481
	mov	esi, eax
482
 
1249 hidnplayr 483
	cmp	word [esi + SOCKET_head.Domain], AF_INET4
484
	je	.af_inet4
485
 
486
	jmp	s_error
487
 
488
  .af_inet4:
489
 
490
	cmp	[esi + SOCKET_head.Type], IP_PROTO_TCP
491
	je	.tcp
492
 
493
	jmp	s_error
494
 
495
  .tcp:
496
 
497
	cmp	[esi + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.backlog], 0
1185 hidnplayr 498
	jz	s_error
1159 hidnplayr 499
 
500
	call	net_socket_alloc
501
	or	eax, eax
1185 hidnplayr 502
	jz	s_error
1159 hidnplayr 503
	mov	edi, eax
504
 
1249 hidnplayr 505
	dec	[esi + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.backlog]
1159 hidnplayr 506
 
1249 hidnplayr 507
	mov	ecx, (SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.end+3)/4
508
	push	esi edi
1159 hidnplayr 509
	rep	movsd
1249 hidnplayr 510
	pop	edi esi
1159 hidnplayr 511
 
1249 hidnplayr 512
	mov	[edi + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.backlog], 0
1159 hidnplayr 513
 
514
	; TODO: fill in structure in ecx
515
 
1249 hidnplayr 516
	mov	[esi + SOCKET_head.end + IPv4_SOCKET.RemoteIP], 0
517
	mov	[esi + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.RemotePort], 0
1159 hidnplayr 518
 
1249 hidnplayr 519
	stdcall net_socket_addr_to_num, edi
1159 hidnplayr 520
	mov	[esp+32], eax
521
 
522
	ret
523
 
524
 
525
 
526
;-----------------------------------------------
527
;
528
; SOCKET_close
529
;
530
;
531
;  IN:  socket number in ecx
532
;  OUT: eax is socket num, -1 on error
533
;
534
;-----------------------------------------------
1206 hidnplayr 535
align 4
1159 hidnplayr 536
socket_close:
537
 
538
	DEBUGF	1,"Socket_close: socknum: %u\n",ecx
539
 
540
	stdcall net_socket_num_to_addr, ecx
541
	or	eax, eax
1185 hidnplayr 542
	jz	s_error
1159 hidnplayr 543
 
1249 hidnplayr 544
	cmp	[eax + SOCKET_head.Domain], AF_INET4
545
	jne	s_error
1159 hidnplayr 546
 
1249 hidnplayr 547
	cmp	[eax + SOCKET_head.Type], IP_PROTO_UDP
1159 hidnplayr 548
	je	.udp
549
 
1249 hidnplayr 550
	cmp	[eax + SOCKET_head.Type], IP_PROTO_ICMP
1159 hidnplayr 551
	je	.icmp
552
 
1249 hidnplayr 553
	cmp	[eax + SOCKET_head.Type], IP_PROTO_TCP
1206 hidnplayr 554
	je	.tcp
1159 hidnplayr 555
 
1185 hidnplayr 556
	jmp	s_error
1159 hidnplayr 557
 
558
  .udp:
559
 
560
	stdcall net_socket_free, eax
561
	mov	dword [esp+32],0
562
	ret
563
 
564
 
565
  .icmp:
566
 
567
 
568
 
569
	ret
570
 
571
  .tcp:
572
 
573
if 1 = 0
574
;local sockAddr dd ?
575
 
576
;        DEBUGF  1, "K : socket_close_tcp (0x%x)\n", ebx
577
	; first, remove any resend entries
578
	pusha
579
 
580
	mov	esi, resendQ
581
	mov	ecx, 0
582
 
583
  .next_resendq:
584
	cmp	ecx, NUMRESENDENTRIES
585
	je	.last_resendq	    ; None left
586
	cmp	[esi + 4], ebx
587
	je	@f		    ; found one
588
	inc	ecx
589
	add	esi, 8
590
	jmp	.next_resendq
591
 
592
    @@: mov	dword[esi + 4], 0
593
	inc	ecx
594
	add	esi, 8
595
	jmp	.next_resendq
596
 
597
  .last_resendq:
598
	popa
599
 
600
	mov	ebx, eax
601
;        mov     [sockAddr], eax
602
 
603
	cmp	[eax + SOCKET.TCBState], TCB_LISTEN
604
	je	.destroy_tcb
605
	cmp	[eax + SOCKET.TCBState], TCB_SYN_SENT
606
	je	.destroy_tcb
607
 
608
; Now construct the response, and queue for sending by IP
609
	mov	eax, EMPTY_QUEUE
610
	call	dequeue
611
	cmp	ax, NO_BUFFER
612
	je	.error
613
 
614
	push	eax
615
 
616
	mov	bl, TH_FIN
617
	xor	ecx, ecx
618
	xor	esi, esi
619
	stdcall build_tcp_Packet, [sockAddr]
620
 
621
	mov	 ebx, [sockAddr]
622
	; increament SND.NXT in socket
623
	lea	esi, [ebx + SOCKET.SND_NXT]
624
	call	inc_inet_esi
625
 
626
	; Get the socket state
627
	mov	eax, [ebx + SOCKET.TCBState]
628
	cmp	eax, TCB_SYN_RECEIVED
629
	je	.fin_wait_1
630
	cmp	eax, TCB_ESTABLISHED
631
	je	.fin_wait_1
632
 
633
	; assume CLOSE WAIT
634
	; Send a fin, then enter last-ack state
635
	mov	[ebx + SOCKET.TCBState], TCB_LAST_ACK
636
	jmp	.send
637
 
638
  .fin_wait_1:
639
	; Send a fin, then enter finwait2 state
640
	mov	[ebx + SOCKET.TCBState], TCB_FIN_WAIT_1
641
 
642
  .send:
643
	mov	eax, NET1OUT_QUEUE
644
	mov	edx, [IP_LIST]
645
;        mov     ecx, [sockAddr]
646
	cmp	edx, [ecx + SOCKET.RemoteIP]
647
	jne	.not_local
648
	mov	eax, IPIN_QUEUE
649
 
650
  .not_local:
651
	; Send it.
652
	pop	ebx
653
	call	queue
654
	jmp	.exit
655
 
656
 
657
  .destroy_tcb:
658
 
659
	stdcall net_socket_free, eax
660
 
661
end if
662
 
663
  .exit:
664
	mov	dword [esp+32],0
665
	ret
666
 
667
 
668
 
669
 
670
;-----------------------------------------------
671
;
672
; SOCKET_receive
673
;
674
;
675
;  IN:  socket number in ecx
1249 hidnplayr 676
;       addr to buffer in edx
677
;       length of buffer in esi
1159 hidnplayr 678
;       flags in edi
679
;  OUT: eax is number of bytes copied, -1 on error
680
;
681
;-----------------------------------------------
1206 hidnplayr 682
align 4
1159 hidnplayr 683
socket_recv:
684
 
1249 hidnplayr 685
	DEBUGF	1,"Socket_receive: socknum: %u bufferaddress: %x, length: %u, flags: %x\n",ecx,edx,esi,edi
1159 hidnplayr 686
 
687
	stdcall net_socket_num_to_addr, ecx		   ; get real socket address
688
	or	eax, eax
1185 hidnplayr 689
	jz	s_error
1159 hidnplayr 690
 
1249 hidnplayr 691
	DEBUGF	1,"Socket pointer: %x\n", eax
1159 hidnplayr 692
 
1249 hidnplayr 693
	get_from_queue (eax + 2048), SOCKET_QUEUE_SIZE, 4*3, s_error
1159 hidnplayr 694
 
695
	mov	edi, edx
1249 hidnplayr 696
	mov	ecx, [esi + socket_queue_entry.data_size]
1159 hidnplayr 697
 
1249 hidnplayr 698
	DEBUGF	1,"Got %u bytes of data\n", ecx
1159 hidnplayr 699
 
1249 hidnplayr 700
	cmp	ecx, edx
701
	jle	.large_enough
702
	DEBUGF	1,"Buffer too small...\n"
703
	jmp	s_error
704
  .large_enough:
1159 hidnplayr 705
 
1249 hidnplayr 706
	push	[esi + socket_queue_entry.data_ptr]
707
	mov	esi, [esi + socket_queue_entry.offset]
708
	add	esi, [esp]
709
	DEBUGF	1,"Source buffer: %x, real addr: %x\n", [esp], esi
1159 hidnplayr 710
 
1249 hidnplayr 711
	mov	dword[esp+32+4], ecx			     ; return number of bytes copied
1159 hidnplayr 712
 
1249 hidnplayr 713
	shr	ecx, 1
714
	jnc	.nb
715
	movsb
716
.nb:	shr	ecx, 1
717
	jnc	.nw
718
	movsw
719
.nw:	rep	movsd
1159 hidnplayr 720
 
1249 hidnplayr 721
	call	kernel_free
1159 hidnplayr 722
 
723
	ret
724
 
725
 
726
;-----------------------------------------------
727
;
728
; SOCKET_send
729
;
730
;
731
;  IN:  socket number in ecx
1206 hidnplayr 732
;       pointer to data in edx
733
;       datalength in esi
1159 hidnplayr 734
;       flags in edi
735
;  OUT: -1 on error
736
;
737
;-----------------------------------------------
1206 hidnplayr 738
align 4
1159 hidnplayr 739
socket_send:
740
 
741
	DEBUGF	1,"Socket_send: socknum: %u sockaddr: %x, length: %u, flags: %x, ",ecx,edx,esi,edi
742
 
743
	stdcall net_socket_num_to_addr, ecx		   ; get real socket address
744
	or	eax, eax
1185 hidnplayr 745
	jz	s_error
1159 hidnplayr 746
 
1249 hidnplayr 747
	cmp	word [eax + SOCKET_head.Domain], AF_INET4
1206 hidnplayr 748
	je	.af_inet4
749
 
750
	jmp	s_error
751
 
1249 hidnplayr 752
;---------
1206 hidnplayr 753
  .af_inet4:
1249 hidnplayr 754
	DEBUGF	1,"Socket type:%u\n", [eax + SOCKET_head.Type]:4
1206 hidnplayr 755
 
1249 hidnplayr 756
	cmp	[eax + SOCKET_head.Type], IP_PROTO_TCP
757
	je	.tcp
1159 hidnplayr 758
 
1249 hidnplayr 759
	cmp	[eax + SOCKET_head.Type], IP_PROTO_UDP
1159 hidnplayr 760
	je	.udp
761
 
1249 hidnplayr 762
	cmp	[eax + SOCKET_head.Type], SOCK_RAW
763
	je	.raw
1159 hidnplayr 764
 
1185 hidnplayr 765
	jmp	s_error
1249 hidnplayr 766
;--------
1159 hidnplayr 767
 
768
  .udp:
769
 
1206 hidnplayr 770
	DEBUGF	1,"type: UDP, "
1159 hidnplayr 771
 
1249 hidnplayr 772
	cmp	[eax + SOCKET_head.end + IPv4_SOCKET.end + UDP_SOCKET.LocalPort],0
773
	jne	@f
1206 hidnplayr 774
 
1208 hidnplayr 775
	push	esi
1249 hidnplayr 776
	mov	ecx, [eax + SOCKET_head.Type]
1206 hidnplayr 777
	call	socket_find_port
778
	test	bx, bx
1208 hidnplayr 779
	pop	esi
1206 hidnplayr 780
	je	s_error
1249 hidnplayr 781
	mov	[eax + SOCKET_head.end + IPv4_SOCKET.end + UDP_SOCKET.LocalPort], bx
1206 hidnplayr 782
 
1249 hidnplayr 783
     @@:
1206 hidnplayr 784
 
1159 hidnplayr 785
	mov	ecx, esi
786
	mov	esi, edx
787
 
1249 hidnplayr 788
	call	UDP_socket_send
1159 hidnplayr 789
 
790
	mov	[esp+32], eax
791
	ret
792
 
1249 hidnplayr 793
  .tcp:
1159 hidnplayr 794
 
1249 hidnplayr 795
	mov	[esp+32], eax
796
	ret
1159 hidnplayr 797
 
1249 hidnplayr 798
;--------
799
  .raw:
800
	cmp	[eax + SOCKET_head.Protocol], IP_PROTO_IP
801
	je	.raw_ip
802
 
803
	cmp	[eax + SOCKET_head.Protocol], IP_PROTO_ICMP
804
	je	.raw_icmp
805
 
806
	jmp	s_error
807
;--------
808
 
809
 
810
  .raw_ip:
811
 
1159 hidnplayr 812
	mov	[esp+32], eax
813
	ret
814
 
815
 
1249 hidnplayr 816
  .raw_icmp:
817
 
818
;        sub     ecx, ICMP_Packet.Data
819
;        mov     esi, edx
820
;        push    ax
821
;        call    IPv4_get_frgmnt_num
822
;        mov     dx, ax
823
;        pop     ax
824
;        shl     edx, 16
825
;        mov     dh , [esi + ICMP_Packet.Type]
826
;        mov     dl , [esi + ICMP_Packet.Code]
827
;        mov     di , [esi + ICMP_Packet.Identifier]
828
;        mov     [eax + SOCKET.LocalPort], di            ; Set localport to the identifier number, so we can receive reply's
829
;        shl     edi, 16
830
;        mov     di , [esi + ICMP_Packet.SequenceNumber]
831
;        add     esi, ICMP_Packet.Data
832
;        mov     ebx, [eax + SOCKET.LocalIP]
833
;        mov     eax, [eax + SOCKET.RemoteIP]
834
;        call    ICMP_create_packet
835
 
836
	mov	[esp+32], eax
1159 hidnplayr 837
	ret
838
 
839
 
840
 
1206 hidnplayr 841
;-----------------------------------------------
842
;
843
; SOCKET_find_free_port (local port)
844
;
845
; works with INET byte order
846
;
847
;  IN:  type in ecx (TCP/UDP)
848
;  OUT: bx = 0 on error, portnumber otherwise
849
;
850
;-----------------------------------------------
851
align 4
852
socket_find_port:
1159 hidnplayr 853
 
1208 hidnplayr 854
	DEBUGF	1,"Socket_find_free_port\n"
1159 hidnplayr 855
 
1206 hidnplayr 856
	cmp	ecx, IP_PROTO_UDP
857
	je	.udp
1159 hidnplayr 858
 
1206 hidnplayr 859
	cmp	ecx, IP_PROTO_TCP
860
	je	.tcp
1159 hidnplayr 861
 
1206 hidnplayr 862
  .udp:
863
	mov	bx, [last_UDP_port]
864
	je	.continue
865
 
866
  .tcp:
867
	mov	bx, [last_TCP_port]
868
 
869
 
870
  .continue:
871
	inc	bx
872
 
873
  .check_only:
874
	mov	esi, net_sockets
875
 
876
  .next_socket:
1249 hidnplayr 877
	mov	esi, [esi + SOCKET_head.NextPtr]
1206 hidnplayr 878
	or	esi, esi
879
	jz	.port_ok
880
 
1249 hidnplayr 881
	cmp	[esi + SOCKET_head.Type], ecx
1206 hidnplayr 882
	jne	.next_socket
883
 
884
	rol	bx, 8
1249 hidnplayr 885
	cmp	[esi + SOCKET_head.end + IPv4_SOCKET.end + UDP_SOCKET.LocalPort], bx
1206 hidnplayr 886
	rol	bx, 8				; this doesnt change the zero flag, does it ?
887
	jne	.next_socket
888
 
889
	cmp	bx, MAX_EPHEMERAL_PORT
890
	jle	.continue
891
 
892
	; todo: WRAP!
893
;        mov     [last_UDP_port], MIN_EPHEMERAL_PORT
894
  .exit:
895
	xor	ebx, ebx
896
 
897
  .port_ok:
898
	rol	bx, 8
899
	ret
900
 
901
;-----------------------------------------------
902
;
903
; SOCKET_check_port (local port)
904
;
905
; works with INET byte order
906
;
907
;  IN:  type in ecx (TCP/UDP)
908
;       port to check in bx
909
;  OUT: bx = 0 on error, unchanged otherwise
910
;
911
;-----------------------------------------------
912
align 4
913
socket_check_port:
914
	mov	esi, net_sockets
915
 
916
  .next_socket:
1249 hidnplayr 917
	mov	esi, [esi + SOCKET_head.NextPtr]
1206 hidnplayr 918
	or	esi, esi
919
	jz	.port_ok
920
 
1249 hidnplayr 921
	cmp	[esi + SOCKET_head.Type], ecx
1206 hidnplayr 922
	jne	.next_socket
923
 
1249 hidnplayr 924
	cmp	[esi + SOCKET_head.end + IPv4_SOCKET.end + UDP_SOCKET.LocalPort], bx
1206 hidnplayr 925
	jne	.next_socket
926
 
927
	xor	ebx, ebx
928
 
929
  .port_ok:
930
	ret
931
 
932
 
933
;-----------------------------------------------
934
;
935
; SOCKET_internal_receiver
936
;
1249 hidnplayr 937
; Updates a socket with received data
1206 hidnplayr 938
;
1249 hidnplayr 939
; Note: the mutex must already be set !
1206 hidnplayr 940
;
1249 hidnplayr 941
;  IN:  eax = socket ptr
942
;       ecx = size
943
;       esi = pointer to buffer
944
;       edi = offset
945
;
1206 hidnplayr 946
;  OUT: xxx
947
;
948
;-----------------------------------------------
949
align 4
950
socket_internal_receiver:
951
 
1249 hidnplayr 952
	DEBUGF 1,"Internal socket receiver: buffer %x, offset: %x\n", esi, edi
1206 hidnplayr 953
 
1249 hidnplayr 954
	push	edi	; offset
955
	push	ecx	; size
956
	push	esi	; data_ptr
957
	mov	esi, esp
958
	add_to_queue (eax + 2048), SOCKET_QUEUE_SIZE, 3*4, .full
959
	DEBUGF	1,"Queued packet successfully\n"
960
	add	esp, 4*3
1206 hidnplayr 961
 
1249 hidnplayr 962
	mov	[eax + SOCKET_head.lock], 0
1206 hidnplayr 963
 
964
	; flag an event to the application
1249 hidnplayr 965
	mov	edx, [eax + SOCKET_head.PID]				; get socket owner PID
1206 hidnplayr 966
	mov	ecx, 1
967
	mov	esi, TASK_DATA + TASKDATA.pid
968
 
969
       .next_pid:
970
	cmp	[esi], edx
971
	je	.found_pid
972
	inc	ecx
973
	add	esi, 0x20
974
	cmp	ecx, [TASK_COUNT]
975
	jbe	.next_pid
976
	ret
977
 
978
       .found_pid:
979
	shl	ecx, 8
1249 hidnplayr 980
	or	[ecx + SLOT_BASE + APPDATA.event_mask], EVENT_NETWORK	; stack event
1206 hidnplayr 981
	mov	[check_idle_semaphore], 200
982
	ret
983
 
1249 hidnplayr 984
  .full:
985
	DEBUGF 1,"Socket %x is full!\n",eax
986
	mov	[eax + SOCKET_head.lock], 0
987
	call	kernel_free
988
	add	esp, 8
1206 hidnplayr 989
	ret
990
 
991
 
992
 
993
 
1159 hidnplayr 994
; Allocate memory for socket data and put new socket into the list
995
; Newly created socket is initialized with calling PID and number and
996
; put into beginning of list (which is a fastest way).
997
;
998
; @return socket structure address in EAX
999
;
1000
proc net_socket_alloc stdcall uses ebx ecx edx edi
1001
	stdcall kernel_alloc, SOCKETBUFFSIZE
1002
	DEBUGF	1, "K : net_socket_alloc (0x%x)\n", eax
1003
	; check if we can allocate needed amount of memory
1004
	or	eax, eax
1005
	jz	.exit
1006
 
1007
	; zero-initialize allocated memory
1008
	push	eax
1009
	mov	edi, eax
1249 hidnplayr 1010
 
1159 hidnplayr 1011
	mov	ecx, SOCKETBUFFSIZE / 4
1012
;        cld
1013
	xor	eax, eax
1014
	rep	stosd
1015
	pop	eax
1016
 
1249 hidnplayr 1017
	init_queue (eax + 2048)
1018
 
1159 hidnplayr 1019
	; add socket to the list by changing pointers
1020
	mov	ebx, net_sockets
1249 hidnplayr 1021
	push	[ebx + SOCKET_head.NextPtr]
1022
	mov	[ebx + SOCKET_head.NextPtr], eax
1023
	mov	[eax + SOCKET_head.PrevPtr], ebx
1159 hidnplayr 1024
	pop	ebx
1249 hidnplayr 1025
	mov	[eax + SOCKET_head.NextPtr], ebx
1159 hidnplayr 1026
	or	ebx, ebx
1027
	jz	@f
1249 hidnplayr 1028
	mov	[ebx + SOCKET_head.PrevPtr], eax
1159 hidnplayr 1029
 
1030
    @@: ; set socket owner PID to the one of calling process
1031
	mov	ebx, [TASK_BASE]
1032
	mov	ebx, [ebx + TASKDATA.pid]
1249 hidnplayr 1033
	mov	[eax + SOCKET_head.PID], ebx
1159 hidnplayr 1034
 
1035
	; find first free socket number and use it
1036
	;mov     edx, ebx
1037
	mov	ebx, net_sockets
1038
	xor	ecx, ecx
1039
  .next_socket_number:
1040
	inc	ecx
1041
  .next_socket:
1249 hidnplayr 1042
	mov	ebx, [ebx + SOCKET_head.NextPtr]
1159 hidnplayr 1043
	or	ebx, ebx
1044
	jz	.last_socket_number
1249 hidnplayr 1045
	cmp	[ebx + SOCKET_head.Number], ecx
1159 hidnplayr 1046
	jne	.next_socket
1047
	;cmp     [ebx + SOCKET.PID], edx
1048
	;jne     .next_socket
1049
	mov	ebx, net_sockets
1050
	jmp	.next_socket_number
1051
 
1052
  .last_socket_number:
1249 hidnplayr 1053
	mov	[eax + SOCKET_head.Number], ecx
1159 hidnplayr 1054
 
1055
  .exit:
1056
	ret
1057
endp
1058
 
1059
; Free socket data memory and pop socket off the list
1060
;
1061
; @param sockAddr is a socket structure address
1062
;
1063
proc net_socket_free stdcall uses ebx ecx edx, sockAddr:DWORD
1064
	mov	eax, [sockAddr]
1065
	DEBUGF	1, "K : net_socket_free (0x%x)\n", eax
1066
	; check if we got something similar to socket structure address
1067
	or	eax, eax
1068
	jz	.error
1069
 
1070
	; make sure sockAddr is one of the socket addresses in the list
1071
	mov	ebx, net_sockets
1072
	;mov     ecx, [TASK_BASE]
1073
	;mov     ecx, [ecx + TASKDATA.pid]
1074
  .next_socket:
1249 hidnplayr 1075
	mov	ebx, [ebx + SOCKET_head.NextPtr]
1159 hidnplayr 1076
	or	ebx, ebx
1077
	jz	.error
1078
	cmp	ebx, eax
1079
	jne	.next_socket
1080
	;cmp     [ebx + SOCKET.PID], ecx
1081
	;jne     .next_socket
1082
 
1083
	; okay, we found the correct one
1084
	; remove it from the list first, changing pointers
1249 hidnplayr 1085
	mov	ebx, [eax + SOCKET_head.NextPtr]
1086
	mov	eax, [eax + SOCKET_head.PrevPtr]
1087
	mov	[eax + SOCKET_head.NextPtr], ebx
1159 hidnplayr 1088
	or	ebx, ebx
1089
	jz	@f
1249 hidnplayr 1090
	mov	[ebx + SOCKET_head.PrevPtr], eax
1159 hidnplayr 1091
 
1249 hidnplayr 1092
	lea	ebx, [eax + SOCKET_head.lock]
1093
	call	wait_mutex
1094
 
1159 hidnplayr 1095
    @@: ; and finally free the memory structure used
1096
	stdcall kernel_free, [sockAddr]
1097
	ret
1098
 
1099
  .error:
1100
	DEBUGF	1, "K :   failed\n"
1101
	ret
1102
endp
1103
 
1104
; Get socket structure address by its number
1105
; Scan through sockets list to find the socket with specified number.
1106
; This proc uses SOCKET.PID indirectly to check if socket is owned by
1107
; calling process.
1108
;
1109
; @param sockNum is a socket number
1110
; @return socket structure address or 0 (not found) in EAX
1111
;
1112
proc net_socket_num_to_addr stdcall uses ebx ecx, sockNum:DWORD
1113
	mov	eax, [sockNum]
1114
	; check if we got something similar to socket number
1115
	or	eax, eax
1116
	jz	.error
1117
 
1118
	; scan through sockets list
1119
	mov	ebx, net_sockets
1120
	;mov     ecx, [TASK_BASE]
1121
	;mov     ecx, [ecx + TASKDATA.pid]
1122
  .next_socket:
1249 hidnplayr 1123
	mov	ebx, [ebx + SOCKET_head.NextPtr]
1159 hidnplayr 1124
	or	ebx, ebx
1125
	jz	.error
1249 hidnplayr 1126
	cmp	[ebx + SOCKET_head.Number], eax
1159 hidnplayr 1127
	jne	.next_socket
1128
	;cmp     [ebx + SOCKET.PID], ecx
1129
	;jne     .next_socket
1130
 
1131
	; okay, we found the correct one
1132
	mov	eax, ebx
1133
	ret
1134
 
1135
  .error:
1136
	xor	eax, eax
1137
	ret
1138
endp
1139
 
1140
; Get socket number by its structure address
1141
; Scan through sockets list to find the socket with specified address.
1142
; This proc uses SOCKET.PID indirectly to check if socket is owned by
1143
; calling process.
1144
;
1145
; @param sockAddr is a socket structure address
1146
; @return socket number (SOCKET.Number) or 0 (not found) in EAX
1147
;
1148
proc net_socket_addr_to_num stdcall uses ebx ecx, sockAddr:DWORD
1149
	mov	eax, [sockAddr]
1150
	; check if we got something similar to socket structure address
1151
	or	eax, eax
1152
	jz	.error
1153
 
1154
	; scan through sockets list
1155
	mov	ebx, net_sockets
1156
	;mov     ecx, [TASK_BASE]
1157
	;mov     ecx, [ecx + TASKDATA.pid]
1158
  .next_socket:
1249 hidnplayr 1159
	mov	ebx, [ebx + SOCKET_head.NextPtr]
1159 hidnplayr 1160
	or	ebx, ebx
1161
	jz	.error
1162
	cmp	ebx, eax
1163
	jne	.next_socket
1164
	;cmp     [ebx + SOCKET.PID], ecx
1165
	;jne     .next_socket
1166
 
1167
	; okay, we found the correct one
1249 hidnplayr 1168
	mov	eax, [ebx + SOCKET_head.Number]
1159 hidnplayr 1169
	ret
1170
 
1171
  .error:
1172
	xor	eax, eax
1173
	ret
1174
endp