Subversion Repositories Kolibri OS

Rev

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