Subversion Repositories Kolibri OS

Rev

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

Rev Author Line No. Line
431 serge 1
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2
;;                                                              ;;
3
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;;
4
;; Distributed under terms of the GNU General Public License    ;;
5
;;                                                              ;;
6
;;  SOCKET.INC                                                  ;;
7
;;                                                              ;;
8
;;  Sockets constants, structures and functions                 ;;
9
;;                                                              ;;
10
;;  Last revision: 11.11.2006                                   ;;
11
;;                                                              ;;
12
;;  This file contains the following:                           ;;
13
;;    is_localport_unused                                       ;;
14
;;    get_free_socket                                           ;;
15
;;    socket_open                                               ;;
16
;;    socket_open_tcp                                           ;;
17
;;    socket_close                                              ;;
18
;;    socket_close_tcp                                          ;;
19
;;    socket_poll                                               ;;
20
;;    socket_status                                             ;;
21
;;    socket_read                                               ;;
22
;;    socket_write                                              ;;
23
;;    socket_write_tcp                                          ;;
24
;;                                                              ;;
25
;;                                                              ;;
26
;;  Changes history:                                            ;;
27
;;   22.09.2003 - [Mike Hibbett] : mikeh@oceanfree.net          ;;
28
;;   11.11.2006 - [Johnny_B] and [smb]                          ;;
29
;;                                                              ;;
30
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
261 hidnplayr 31
 
593 mikedld 32
$Revision: 914 $
33
 
34
 
261 hidnplayr 35
;
36
;  Socket Descriptor + Buffer
37
;
38
;    0                   1                   2                   3
39
;    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
40
;
41
;   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
42
;  0|                    Status ( of this buffer )                  |
43
;   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
44
;  4|  Application Process ID                                       |
45
;   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
46
;  8|                  Local IP Address                             |
47
;   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
48
; 12| Local IP Port                 | Unused ( set to 0 )           |
49
;   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
50
; 16|                  Remote IP Address                            |
51
;   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
52
; 20| Remote IP Port                | Unused ( set to 0 )           |
53
;   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
54
; 24|   Rx Data Count                                   INTEL format|
55
;   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
56
; 28|                 TCB STATE                         INTEL format|
57
;   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
58
; 32|   TCB Timer (seconds)                             INTEL format|
59
;   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
60
; 36| ISS (Inital Sequence # used by this connection )   INET format|
61
;   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
62
; 40| IRS ( Inital Receive Sequence # )                  INET format|
63
;   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
64
; 44| SND.UNA  Seq # of unack'ed sent packets            INET format|
65
;   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
66
; 48| SND.NXT  Next send seq # to use                    INET format|
67
;   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
68
; 52| SND.WND  Send window                               INET format|
69
;   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
70
; 56| RCV.NXT  Next expected receive sequence #          INET format|
71
;   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
72
; 60| RCV.WND  Receive window                            INET format|
73
;   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
74
; 64| SEG.LEN  Segment length                           INTEL format|
75
;   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
76
; 68| SEG.WND  Segment window                           INTEL format|
77
;   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
78
; 72| Retransmit queue # NOW WINDOW SIZE TIMER          INTEL format|
79
;   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
914 serge 80
; 76|       RX Data Buffer                                          |
261 hidnplayr 81
;   +-+-+-..........                                               -+
82
 
83
 
84
; so, define struct
85
struc SOCKET
914 serge 86
{
87
   .PrevPtr		    dd	 ?
88
   .NextPtr		    dd	 ?
89
   .Status		    dd	 ?  ;+00 - Status ( of this buffer )
379 serge 90
   .PID 		    dd	 ?  ;+04 - Application Process ID
323 hidnplayr 91
   .LocalIP		    dd	 ?  ;+08 -  Local IP Address
92
   .LocalPort		    dw	 ?  ;+12 - Local Port
93
   .RemoteIP		    dd	 ?  ;+16 - Remote IP Address
94
   .RemotePort		    dw	 ?  ;+20 - Remote Port
914 serge 95
   .OrigRemoteIP	    dd	 ?
96
   .OrigRemotePort	    dw	 ?
323 hidnplayr 97
   .rxDataCount 	    dd	 ?  ;+24 - Rx Data Count
98
   .TCBState		    dd	 ?  ;+28 - TCB STATE
379 serge 99
   .TCBTimer		    dd	 ?  ;+32 - TCB Timer (seconds)
323 hidnplayr 100
   .ISS 		    dd	 ?  ;+36 - Initial Send Sequence
101
   .IRS 		    dd	 ?  ;+40 - Initial Receive Sequence
102
   .SND_UNA		    dd	 ?  ;+44 - Sequence number of unack'ed sent packets
379 serge 103
   .SND_NXT		    dd	 ?  ;+48 - Next send sequence number to use
323 hidnplayr 104
   .SND_WND		    dd	 ?  ;+52 - Send window
105
   .RCV_NXT		    dd	 ?  ;+56 - Next receive sequence number to use
106
   .RCV_WND		    dd	 ?  ;+60 - Receive window
107
   .SEG_LEN		    dd	 ?  ;+64 - Segment length
108
   .SEG_WND		    dd	 ?  ;+68 - Segment window
379 serge 109
   .wndsizeTimer	    dd	 ?  ;+72 - Retransmit queue # NOW WINDOW SIZE TIMER
323 hidnplayr 110
   .rxData		    dd	 ?  ;+76 - receive data buffer here
261 hidnplayr 111
}
112
 
113
virtual at 0
114
  SOCKET SOCKET
115
end virtual
116
 
379 serge 117
; simple macro calcing real memory address of SOCKET struct by socket's
914 serge 118
;macro   Index2RealAddr reg
119
;{
120
;        shl     reg, 12
121
;    add     reg, sockets
122
;}
261 hidnplayr 123
 
124
;Constants
125
; current socket statuses
914 serge 126
SOCK_EMPTY	   =	 0	  ; socket not in use
127
SOCK_OPEN	   =	 1	  ; open issued, but no data sent
261 hidnplayr 128
 
129
; TCP opening modes
323 hidnplayr 130
SOCKET_PASSIVE	   equ	   0
131
SOCKET_ACTIVE	   equ	   1
261 hidnplayr 132
 
914 serge 133
proc net_socket_alloc stdcall uses ebx ecx edx edi
134
    mov ecx, SOCKETBUFFSIZE
135
    mov edx, PG_SW
136
    call @mem_alloc@8
137
	DEBUGF	1, "K : net_socket_alloc (0x%x)\n", eax
138
	or	eax, eax
139
	jz	.exit
140
 
141
	push	eax
142
	mov	edi, eax
143
	mov	ecx, SOCKETBUFFSIZE / 4
144
	cld
145
	xor	eax, eax
146
	rep	stosd
147
	pop	eax
148
 
149
	mov	ebx, net_sockets
150
	push	[ebx + SOCKET.NextPtr]
151
	mov	[ebx + SOCKET.NextPtr], eax
152
	mov	[eax + SOCKET.PrevPtr], ebx
153
	pop	ebx
154
	mov	[eax + SOCKET.NextPtr], ebx
155
	or	ebx, ebx
156
	jz	@f
157
	mov	[ebx + SOCKET.PrevPtr], eax
158
 
159
    @@: mov	ebx, [TASK_BASE]
160
	mov	ebx, [ebx + TASKDATA.pid]
161
	mov	[eax + SOCKET.PID], ebx
162
 
163
  .exit:
164
	ret
165
endp
166
 
167
proc net_socket_free stdcall uses ebx ecx edx, sock:DWORD
168
	mov	eax, [sock]
169
	DEBUGF	1, "K : net_socket_free (0x%x)\n", eax
170
	or	eax, eax
171
	jz	.error
172
 
173
	mov	ebx, net_sockets
174
	mov	ecx, [TASK_BASE]
175
	mov	ecx, [ecx + TASKDATA.pid]
176
  .next_socket:
177
	mov	ebx, [ebx + SOCKET.NextPtr]
178
	or	ebx, ebx
179
	jz	.error
180
	cmp	ebx, eax
181
	jne	.next_socket
182
	;cmp     [ebx + SOCKET.PID], ecx
183
	;jne     .next_socket
184
 
185
	mov	ebx, [eax + SOCKET.NextPtr]
186
	mov	eax, [eax + SOCKET.PrevPtr]
187
	mov	[eax + SOCKET.NextPtr], ebx
188
	or	ebx, ebx
189
	jz	@f
190
	mov	[ebx + SOCKET.PrevPtr], eax
191
 
192
@@:
193
    mov ecx, [sock]
194
    call @mem_free@4
195
	ret
196
 
197
  .error:
198
	DEBUGF	1, "K :   failed\n"
199
	ret
200
endp
201
 
202
proc net_socket_num_to_addr stdcall uses ebx ecx, x:DWORD
203
; FIXME: do real transform
204
	mov	eax, [x]
205
	mov	ebx, net_sockets
206
	mov	ecx, [TASK_BASE]
207
	mov	ecx, [ecx + TASKDATA.pid]
208
  .next_socket:
209
	mov	ebx, [ebx + SOCKET.NextPtr]
210
	or	ebx, ebx
211
	jz	.error
212
	cmp	ebx, eax
213
	jne	.next_socket
214
	;cmp     [ebx + SOCKET.PID], ecx
215
	;jne     .next_socket
216
	ret
217
 
218
  .error:
219
	xor	eax, eax
220
	ret
221
endp
222
 
223
proc net_socket_addr_to_num stdcall uses ebx ecx, x:DWORD
224
; FIXME: do real transform
225
	mov	eax, [x]
226
	mov	ebx, net_sockets
227
	mov	ecx, [TASK_BASE]
228
	mov	ecx, [ecx + TASKDATA.pid]
229
  .next_socket:
230
	mov	ebx, [ebx + SOCKET.NextPtr]
231
	or	ebx, ebx
232
	jz	.error
233
	cmp	ebx, eax
234
	jne	.next_socket
235
	;cmp     [ebx + SOCKET.PID], ecx
236
	;jne     .next_socket
237
	ret
238
 
239
  .error:
240
	xor	eax, eax
241
	ret
242
endp
243
 
261 hidnplayr 244
;***************************************************************************
245
;   Function
246
;      is_localport_unused
247
;
248
;   Description
249
;         scans through all the active sockets , looking to see if the
250
;      port number specified in bx is in use as a localport number.
251
;      This is useful when you want a to generate a unique local port
252
;      number.
253
;          On return, eax = 1 for free, 0 for in use
254
;
255
;***************************************************************************
914 serge 256
proc is_localport_unused stdcall
261 hidnplayr 257
 
914 serge 258
	xchg	bl, bh
261 hidnplayr 259
 
914 serge 260
	xor	eax, eax			; Assume the return value is 'free'
261
	inc	al
262
	mov	edx, net_sockets
261 hidnplayr 263
 
914 serge 264
  .next_socket:
265
	mov	edx, [edx + SOCKET.NextPtr]
266
	or	edx, edx
267
	jz	.exit
268
	cmp	[edx + SOCKET.LocalPort], bx
269
	jne	.next_socket			; Return back if the port is not occupied
261 hidnplayr 270
 
914 serge 271
	dec	al				; return 'in use'
261 hidnplayr 272
 
914 serge 273
  .exit:
261 hidnplayr 274
    ret
914 serge 275
endp
261 hidnplayr 276
 
277
 
278
;***************************************************************************
279
;   Function
280
;      socket_open
281
;
282
;   Description
283
;       find a free socket
284
;       local port in ebx
285
;       remote port in ecx
286
;       remote ip in edx
287
;       return socket # in eax, -1 if none available
288
;
289
;***************************************************************************
914 serge 290
proc socket_open stdcall
291
	call	net_socket_alloc
292
	or	eax, eax
293
	jz	.error
261 hidnplayr 294
 
914 serge 295
	DEBUGF	1, "K : socket_open (0x%x)\n", eax
261 hidnplayr 296
 
297
    push    eax
298
 
914 serge 299
	mov	[eax + SOCKET.Status], SOCK_OPEN
323 hidnplayr 300
    xchg    bh, bl
301
    mov     [eax + SOCKET.LocalPort], bx
302
    xchg    ch, cl
303
    mov     [eax + SOCKET.RemotePort], cx
261 hidnplayr 304
 
305
    mov     ebx, [stack_ip]
379 serge 306
    mov     [eax + SOCKET.LocalIP], ebx
307
    mov     [eax + SOCKET.RemoteIP], edx
261 hidnplayr 308
 
914 serge 309
	;pop     eax      ; Get the socket number back, so we can return it
310
	stdcall net_socket_addr_to_num
311
	ret
261 hidnplayr 312
 
914 serge 313
  .error:
314
	DEBUGF	1, "K : socket_open (fail)\n"
315
	or	eax, -1
261 hidnplayr 316
    ret
914 serge 317
endp
261 hidnplayr 318
 
319
 
320
;***************************************************************************
321
;   Function
322
;      socket_open_tcp
323
;
324
;   Description
325
;       Opens a TCP socket in PASSIVE or ACTIVE mode
326
;       find a free socket
327
;       local port in ebx ( intel format )
328
;       remote port in ecx ( intel format )
329
;       remote ip in edx ( in Internet byte order )
330
;       Socket open mode in esi  ( SOCKET_PASSIVE or SOCKET_ACTIVE )
331
;       return socket # in eax, -1 if none available
332
;
333
;***************************************************************************
914 serge 334
proc socket_open_tcp stdcall
335
local sockAddr dd ?
261 hidnplayr 336
 
914 serge 337
	cmp	esi, SOCKET_PASSIVE
338
	jne	.skip_port_check
261 hidnplayr 339
 
914 serge 340
	push	ebx
341
	mov	eax, ebx
342
	xchg	al, ah
343
	mov	ebx, net_sockets
261 hidnplayr 344
 
914 serge 345
  .next_socket:
346
	mov	ebx, [ebx + SOCKET.NextPtr]
347
	or	ebx, ebx
348
	jz	.last_socket
349
	cmp	[ebx + SOCKET.TCBState], TCB_LISTEN
350
	jne	.next_socket
351
	cmp	[ebx + SOCKET.LocalPort], ax
352
	jne	.next_socket
261 hidnplayr 353
 
914 serge 354
	xchg	al, ah
355
	DEBUGF	1, "K : error: port %u is listened by 0x%x\n", ax, ebx
356
	pop	ebx
357
	jmp	.error
358
 
359
  .last_socket:
360
	pop	ebx
361
 
362
  .skip_port_check:
363
	call	net_socket_alloc
364
	or	eax, eax
365
	jz	.error
366
 
367
	DEBUGF	1, "K : socket_open_tcp (0x%x)\n", eax
368
 
369
	mov	[sockAddr], eax
370
 
261 hidnplayr 371
    ; TODO - check this works!
914 serge 372
	;xxx: already 0 (intialized by net_socket_alloc)
373
	;mov     [eax + SOCKET.wndsizeTimer], 0     ; Reset the window timer.
261 hidnplayr 374
 
323 hidnplayr 375
	xchg	bh, bl
379 serge 376
	mov	[eax + SOCKET.LocalPort], bx
323 hidnplayr 377
	xchg	ch, cl
379 serge 378
	mov	[eax + SOCKET.RemotePort], cx
914 serge 379
	mov	[eax + SOCKET.OrigRemotePort], cx
261 hidnplayr 380
    mov     ebx, [stack_ip]
379 serge 381
    mov     [eax + SOCKET.LocalIP], ebx
382
    mov     [eax + SOCKET.RemoteIP], edx
914 serge 383
	mov	[eax + SOCKET.OrigRemoteIP], edx
261 hidnplayr 384
 
385
    mov     ebx, TCB_LISTEN
386
    cmp     esi, SOCKET_PASSIVE
914 serge 387
	je	@f
261 hidnplayr 388
    mov     ebx, TCB_SYN_SENT
914 serge 389
    @@: mov	[eax + SOCKET.TCBState], ebx		; Indicate the state of the TCB
261 hidnplayr 390
 
391
    cmp     ebx, TCB_LISTEN
914 serge 392
	je	.exit
261 hidnplayr 393
 
394
    ; Now, if we are in active mode, then we have to send a SYN to the specified remote port
395
    mov     eax, EMPTY_QUEUE
396
    call    dequeue
397
    cmp     ax, NO_BUFFER
914 serge 398
	je	.exit
261 hidnplayr 399
 
400
    push    eax
401
 
914 serge 402
	mov	bl, TH_SYN
403
	xor	ecx, ecx
404
	stdcall build_tcp_packet, [sockAddr]
261 hidnplayr 405
 
406
    mov     eax, NET1OUT_QUEUE
407
 
408
    mov     edx, [stack_ip]
914 serge 409
	mov	ecx, [sockAddr]
410
	cmp	edx, [ecx + SOCKET.RemoteIP]
411
	jne	.not_local
261 hidnplayr 412
    mov     eax, IPIN_QUEUE
413
 
914 serge 414
  .not_local:
261 hidnplayr 415
       ; Send it.
416
    pop     ebx
417
    call    queue
418
 
914 serge 419
	mov	esi, [sockAddr]
261 hidnplayr 420
 
421
    ; increment SND.NXT in socket
914 serge 422
	add	esi, SOCKET.SND_NXT
261 hidnplayr 423
    call    inc_inet_esi
424
 
914 serge 425
  .exit:
426
	mov	ebx, [sockAddr]
427
	mov	[ebx + SOCKET.Status], SOCK_OPEN
428
	;pop     eax      ; Get the socket number back, so we can return it
429
	stdcall net_socket_addr_to_num, ebx
430
	ret
261 hidnplayr 431
 
914 serge 432
  .error:
433
	DEBUGF	1, "K : socket_open_tcp (fail)\n"
434
	or	eax, -1
261 hidnplayr 435
    ret
914 serge 436
endp
261 hidnplayr 437
 
438
 
439
;***************************************************************************
440
;   Function
441
;      socket_close
442
;
443
;   Description
444
;       socket # in ebx
445
;       returns 0 for ok, -1 for socket not open (fail)
446
;
447
;***************************************************************************
914 serge 448
proc socket_close stdcall
449
	DEBUGF	1, "K : socket_close (0x%x)\n", ebx
450
	stdcall net_socket_num_to_addr, ebx
451
	or	eax, eax
452
	jz	.error
261 hidnplayr 453
 
914 serge 454
	cmp	[eax + SOCKET.Status], dword SOCK_EMPTY
455
	jz	.error
456
 
261 hidnplayr 457
    ; Clear the socket varaibles
914 serge 458
	stdcall net_socket_free, eax
459
;        mov     edi, eax
460
;        xor     eax, eax
461
;        mov     ecx, SOCKETHEADERSIZE
462
;        cld
463
;        rep     stosb
464
 
261 hidnplayr 465
    xor     eax, eax
914 serge 466
	ret
261 hidnplayr 467
 
914 serge 468
  .error:
469
	DEBUGF	1, "K : socket_close (fail)\n"
470
	or	eax, -1
261 hidnplayr 471
    ret
914 serge 472
endp
261 hidnplayr 473
 
474
 
475
;***************************************************************************
476
;   Function
477
;      socket_close_tcp
478
;
479
;   Description
480
;       socket # in ebx
481
;       returns 0 for ok, -1 for socket not open (fail)
482
;
483
;***************************************************************************
914 serge 484
proc socket_close_tcp stdcall
485
local sockAddr dd ?
486
	DEBUGF	1, "K : socket_close_tcp (0x%x)\n", ebx
261 hidnplayr 487
    ; first, remove any resend entries
488
    pusha
489
 
490
    mov     esi, resendQ
491
    mov     ecx, 0
492
 
914 serge 493
  .next_resendq:
261 hidnplayr 494
    cmp     ecx, NUMRESENDENTRIES
914 serge 495
	je	.last_resendq	    ; None left
496
	;cmp     [esi], bl                               ; XTODO: bl -> ebx
497
	cmp	[esi + 4], ebx
498
	je	@f		    ; found one
261 hidnplayr 499
    inc     ecx
914 serge 500
	add	esi, 8
501
	jmp	.next_resendq
261 hidnplayr 502
 
914 serge 503
    ;@@: mov     byte[esi], 0xff                         ; XTODO: 0xff -> 0
504
    @@: mov	dword[esi + 4], 0
505
	inc	ecx
506
	add	esi, 8
507
	jmp	.next_resendq
261 hidnplayr 508
 
914 serge 509
  .last_resendq:
510
	popa
261 hidnplayr 511
 
914 serge 512
	stdcall net_socket_num_to_addr, ebx
513
	or	eax, eax
514
	jz	.error
261 hidnplayr 515
 
914 serge 516
	mov	ebx, eax
517
	mov	[sockAddr], eax
518
	cmp	[ebx + SOCKET.Status], SOCK_EMPTY
519
	je	.error
261 hidnplayr 520
 
914 serge 521
	cmp	[ebx + SOCKET.TCBState], TCB_LISTEN		;xxx
522
	je	.destroy_tcb					;xxx
523
	cmp	[ebx + SOCKET.TCBState], TCB_SYN_SENT		;xxx
524
	je	.destroy_tcb					;xxx
525
 
261 hidnplayr 526
    ; Now construct the response, and queue for sending by IP
527
    mov     eax, EMPTY_QUEUE
528
    call    dequeue
529
    cmp     ax, NO_BUFFER
914 serge 530
	je	.error
261 hidnplayr 531
 
532
    push    eax
533
 
914 serge 534
;xxx    mov     bl, TH_FIN + TH_ACK
535
	mov	bl, TH_FIN					;xxx
536
	xor	ecx, ecx
537
	xor	esi, esi
538
	stdcall build_tcp_packet, [sockAddr]
261 hidnplayr 539
 
914 serge 540
	mov	 ebx, [sockAddr]
261 hidnplayr 541
    ; increament SND.NXT in socket
914 serge 542
	lea	esi, [ebx + SOCKET.SND_NXT]
261 hidnplayr 543
    call    inc_inet_esi
544
 
545
 
546
    ; Get the socket state
547
    mov     eax, [ebx + SOCKET.TCBState]
914 serge 548
;xxx    cmp     eax, TCB_LISTEN
549
;xxx    je      .destroy_tcb
550
;xxx    cmp     eax, TCB_SYN_SENT
551
;xxx    je      .destroy_tcb
261 hidnplayr 552
    cmp     eax, TCB_SYN_RECEIVED
914 serge 553
	je	.fin_wait_1
261 hidnplayr 554
    cmp     eax, TCB_ESTABLISHED
914 serge 555
	je	.fin_wait_1
261 hidnplayr 556
 
557
    ; assume CLOSE WAIT
558
    ; Send a fin, then enter last-ack state
914 serge 559
	; TODO: check if it's really a TCB_CLOSE_WAIT
560
	mov	[ebx + SOCKET.TCBState], TCB_LAST_ACK
561
	jmp	.send
261 hidnplayr 562
 
914 serge 563
  .fin_wait_1:
261 hidnplayr 564
    ; Send a fin, then enter finwait2 state
914 serge 565
	mov	[ebx + SOCKET.TCBState], TCB_FIN_WAIT_1
261 hidnplayr 566
 
914 serge 567
  .send:
261 hidnplayr 568
    mov     eax, NET1OUT_QUEUE
569
 
570
    mov     edx, [stack_ip]
914 serge 571
	mov	ecx, [sockAddr]
572
	cmp	edx, [ecx + SOCKET.RemoteIP]
573
	jne	.not_local
261 hidnplayr 574
    mov     eax, IPIN_QUEUE
575
 
914 serge 576
  .not_local:
261 hidnplayr 577
       ; Send it.
578
    pop     ebx
579
    call    queue
914 serge 580
	jmp	.exit
261 hidnplayr 581
 
914 serge 582
  .destroy_tcb:
583
;xxx    pop     eax
584
 
585
	; Clear the socket variables
586
;xxx    stdcall net_socket_free, [sockAddr]
587
	stdcall net_socket_free, ebx
588
 
589
  .exit:
261 hidnplayr 590
    xor     eax, eax
914 serge 591
	ret
261 hidnplayr 592
 
914 serge 593
  .error:
594
	DEBUGF	1, "K : socket_close_tcp (fail)\n"
595
	or	eax, -1
261 hidnplayr 596
    ret
914 serge 597
endp
261 hidnplayr 598
 
599
 
600
;***************************************************************************
601
;   Function
602
;      socket_poll
603
;
604
;   Description
605
;       socket # in ebx
606
;       returns count in eax.
607
;
608
;***************************************************************************
914 serge 609
proc socket_poll stdcall
610
;        DEBUGF  1, "socket_poll(0x%x)\n", ebx
611
	stdcall net_socket_num_to_addr, ebx
612
	or	eax, eax
613
	jz	.error
261 hidnplayr 614
 
914 serge 615
	mov	eax, [eax + SOCKET.rxDataCount]
261 hidnplayr 616
    ret
617
 
914 serge 618
  .error:
619
	;or      eax, -1
620
	xor	eax, eax
621
	ret
622
endp
261 hidnplayr 623
 
624
 
625
;***************************************************************************
626
;   Function
627
;      socket_status
628
;
629
;   Description
630
;       socket # in ebx
631
;       returns TCB state in eax.
632
;
633
;***************************************************************************
914 serge 634
proc socket_status stdcall
635
;;       DEBUGF  1, "socket_status(0x%x)\n", ebx
636
	stdcall net_socket_num_to_addr, ebx
637
	or	eax, eax
638
	jz	.error
261 hidnplayr 639
 
914 serge 640
	mov	eax, [eax + SOCKET.TCBState]
641
	ret
642
 
643
  .error:
644
	;or      eax, -1
645
	xor	eax, eax
261 hidnplayr 646
    ret
914 serge 647
endp
261 hidnplayr 648
 
914 serge 649
;    Index2RealAddr ebx
650
;    mov     eax, [ebx + SOCKET.TCBState]
651
;
652
;    ret
261 hidnplayr 653
 
654
 
655
;***************************************************************************
656
;   Function
657
;      socket_read
658
;
659
;   Description
660
;       socket # in ebx
661
;       returns # of bytes remaining in eax, data in bl
662
;
663
;***************************************************************************
914 serge 664
proc socket_read stdcall
665
;        DEBUGF  1, "socket_read(0x%x)\n", ebx
666
	stdcall net_socket_num_to_addr, ebx
667
	or	eax, eax
668
	jz	.error
669
 
670
	mov	ebx, eax
323 hidnplayr 671
    mov     eax, [ebx + SOCKET.rxDataCount]	    ; get count of bytes
261 hidnplayr 672
    test    eax, eax
914 serge 673
	jz	.error
261 hidnplayr 674
 
675
    dec     eax
323 hidnplayr 676
    mov     esi, ebx		; esi is address of socket
677
    mov     [ebx + SOCKET.rxDataCount], eax	    ; store new count
914 serge 678
	;movzx   ebx, byte[ebx + SOCKET.rxData]  ; get the byte
679
	movzx	ebx, byte[ebx + SOCKETHEADERSIZE]  ; get the byte
261 hidnplayr 680
    add     esi, SOCKETHEADERSIZE
681
    mov     edi, esi
682
    inc     esi
683
 
684
    mov     ecx, (SOCKETBUFFSIZE - SOCKETHEADERSIZE) / 4
914 serge 685
	lea	edi, [ebx + SOCKETHEADERSIZE]
686
	lea	esi, [edi + 1]
261 hidnplayr 687
    cld
688
    rep     movsd
689
 
914 serge 690
	ret
261 hidnplayr 691
 
914 serge 692
  .error:
693
	;or      eax, -1
694
	xor	eax, eax
695
	xor	ebx, ebx
261 hidnplayr 696
    ret
914 serge 697
endp
261 hidnplayr 698
 
699
 
323 hidnplayr 700
;***************************************************************************
701
;   Function
702
;      socket_read_packet
703
;
704
;   Description
705
;       socket # in ebx
706
;       datapointer # in ecx
707
;       buffer size in edx
708
;       returns # of bytes copied in eax
709
;
710
;***************************************************************************
914 serge 711
proc socket_read_packet stdcall
712
;        DEBUGF  1, "socket_read_packet(0x%x)\n", ebx
713
	stdcall net_socket_num_to_addr, ebx		   ; get real socket address
714
	or	eax, eax
715
	jz	.error
716
 
717
	mov	ebx, eax
323 hidnplayr 718
    mov     eax, [ebx + SOCKET.rxDataCount]		   ; get count of bytes
719
    test    eax, eax					   ; if count of bytes is zero..
720
    jz	    .exit					   ; exit function (eax will be zero)
261 hidnplayr 721
 
323 hidnplayr 722
    test    edx, edx					   ; if buffer size is zero, copy all data
914 serge 723
	jz	.copy_all_bytes
323 hidnplayr 724
    cmp     edx, eax					   ; if buffer size is larger then the bytes of data, copy all data
914 serge 725
	jge	.copy_all_bytes
323 hidnplayr 726
 
727
    sub     eax, edx					   ; store new count (data bytes in buffer - bytes we're about to copy)
728
    mov     [ebx + SOCKET.rxDataCount], eax		   ;
729
    push    eax
730
    mov     eax, edx					   ; number of bytes we want to copy must be in eax
914 serge 731
	call	.start_copy				   ; copy to the application
323 hidnplayr 732
 
733
    mov     esi, ebx					   ; now we're going to copy the remaining bytes to the beginning
734
    add     esi, SOCKETHEADERSIZE			   ; we dont need to copy the header
735
    mov     edi, esi					   ; edi is where we're going to copy to
736
    add     esi, edx					   ; esi is from where we copy
737
    pop     ecx 					   ; count of bytes we have left
738
    push    ecx 					   ; push it again so we can re-use it later
739
    shr     ecx, 2					   ; divide eax by 4
740
    cld
741
    rep     movsd					   ; copy all full dwords
742
    pop     ecx
743
    and     ecx, 3
744
    rep     movsb					   ; copy remaining bytes
745
 
914 serge 746
  .exit:
323 hidnplayr 747
    ret 						   ; at last, exit
748
 
914 serge 749
  .error:
750
	;or      eax, -1
751
	xor	eax, eax
752
	ret
753
 
754
  .copy_all_bytes:
323 hidnplayr 755
    xor     esi, esi
756
    mov     [ebx + SOCKET.rxDataCount], esi		   ; store new count (zero)
914 serge 757
	call	.start_copy
758
	ret
323 hidnplayr 759
 
914 serge 760
  .start_copy:
761
	mov	edi, ecx
762
	mov	esi, ebx
323 hidnplayr 763
    add     esi, SOCKETHEADERSIZE			   ; we dont need to copy the header
764
    mov     ecx, eax					   ; eax is count of bytes
765
    push    ecx
766
    shr     ecx, 2					   ; divide eax by 4
767
    cld 						   ; copy all full dwords
914 serge 768
	rep	movsd
323 hidnplayr 769
    pop     ecx
770
    and     ecx, 3
771
    rep     movsb					   ; copy the rest bytes
914 serge 772
	retn						   ; exit, or go back to shift remaining bytes if any
773
endp
323 hidnplayr 774
 
775
 
261 hidnplayr 776
;***************************************************************************
777
;   Function
778
;      socket_write
779
;
780
;   Description
781
;       socket in ebx
782
;       # of bytes to write in ecx
783
;       pointer to data in edx
784
;       returns 0 in eax ok, -1 == failed ( invalid socket, or
785
;       could not queue IP packet )
786
;
787
;***************************************************************************
914 serge 788
proc socket_write stdcall
789
;        DEBUGF  1, "socket_write(0x%x)\n", ebx
790
	stdcall net_socket_num_to_addr, ebx		   ; get real socket address
791
	or	eax, eax
792
	jz	.error
261 hidnplayr 793
 
914 serge 794
	mov	ebx, eax
795
 
261 hidnplayr 796
    ; If the socket is invalid, return with an error code
914 serge 797
	cmp	[ebx + SOCKET.Status], SOCK_EMPTY
798
	je	.error
261 hidnplayr 799
 
800
    mov     eax, EMPTY_QUEUE
801
    call    dequeue
802
    cmp     ax, NO_BUFFER
914 serge 803
	je	.error
261 hidnplayr 804
 
805
    ; Save the queue entry number
806
    push    eax
807
 
808
    ; save the pointers to the data buffer & size
809
    push    edx
810
    push    ecx
811
 
812
    ; convert buffer pointer eax to the absolute address
813
    mov     ecx, IPBUFFSIZE
814
    mul     ecx
815
    add     eax, IPbuffs
816
 
817
    mov     edx, eax
818
 
819
    ; So, ebx holds the socket ptr, edx holds the IPbuffer ptr
820
 
914 serge 821
	; Fill in the IP header (some data is in the socket descriptor)
822
	mov	eax, [ebx + SOCKET.LocalIP]
823
	mov	[edx + IP_PACKET.SourceAddress], eax
824
	mov	eax, [ebx + SOCKET.RemoteIP]
825
	mov	[edx + IP_PACKET.DestinationAddress], eax
261 hidnplayr 826
 
914 serge 827
	mov	[edx + IP_PACKET.VersionAndIHL], 0x45
828
	mov	[edx + IP_PACKET.TypeOfService], 0
261 hidnplayr 829
 
323 hidnplayr 830
    pop     eax 		  ; Get the UDP data length
261 hidnplayr 831
    push    eax
832
 
323 hidnplayr 833
    add     eax, 20 + 8 	  ; add IP header and UDP header lengths
914 serge 834
	xchg	al, ah
835
	mov	[edx + IP_PACKET.TotalLength], ax
836
	xor	eax, eax
837
	mov	[edx + IP_PACKET.Identification], ax
838
	mov	[edx + IP_PACKET.FlagsAndFragmentOffset], 0x0040
839
	mov	[edx + IP_PACKET.TimeToLive], 0x20
840
	mov	[edx + IP_PACKET.Protocol], PROTOCOL_UDP
261 hidnplayr 841
 
842
    ; Checksum left unfilled
914 serge 843
	mov	[edx + IP_PACKET.HeaderChecksum], ax
261 hidnplayr 844
 
914 serge 845
	; Fill in the UDP header (some data is in the socket descriptor)
846
	mov	ax, [ebx + SOCKET.LocalPort]
847
	mov	[edx + 20 + UDP_PACKET.SourcePort], ax
261 hidnplayr 848
 
914 serge 849
	mov	ax, [ebx + SOCKET.RemotePort]
850
	mov	[edx + 20 + UDP_PACKET.DestinationPort], ax
261 hidnplayr 851
 
852
    pop     eax
853
    push    eax
854
 
855
    add     eax, 8
914 serge 856
	xchg	al, ah
857
	mov	[edx + 20 + UDP_PACKET.Length], ax
261 hidnplayr 858
 
859
    ; Checksum left unfilled
914 serge 860
	xor	eax, eax
861
	mov	[edx + 20 + UDP_PACKET.Checksum], ax
261 hidnplayr 862
 
323 hidnplayr 863
    pop     ecx 		 ; count of bytes to send
864
    mov     ebx, ecx		; need the length later
865
    pop     eax 		 ; get callers ptr to data to send
261 hidnplayr 866
 
867
    ; Get the address of the callers data
379 serge 868
    mov     edi, [TASK_BASE]
261 hidnplayr 869
    add     edi, TASKDATA.mem_start
870
    add     eax, [edi]
871
    mov     esi, eax
872
 
873
    mov     edi, edx
874
    add     edi, 28
875
    cld
323 hidnplayr 876
    rep     movsb		; copy the data across
261 hidnplayr 877
 
878
    ; we have edx as IPbuffer ptr.
879
    ; Fill in the UDP checksum
880
    ; First, fill in pseudoheader
914 serge 881
	mov	eax, [edx + IP_PACKET.SourceAddress]
261 hidnplayr 882
    mov     [pseudoHeader], eax
914 serge 883
	mov	eax, [edx + IP_PACKET.DestinationAddress]
884
	mov	[pseudoHeader + 4], eax
885
	mov	word[pseudoHeader + 8], PROTOCOL_UDP shl 8 + 0	    ; 0 + protocol
261 hidnplayr 886
    add     ebx, 8
887
    mov     eax, ebx
914 serge 888
	xchg	al, ah
889
	mov	[pseudoHeader + 10], ax
261 hidnplayr 890
 
891
    mov     eax, pseudoHeader
892
    mov     [checkAdd1], eax
893
    mov     [checkSize1], word 12
894
    mov     eax, edx
895
    add     eax, 20
896
    mov     [checkAdd2], eax
897
    mov     eax, ebx
323 hidnplayr 898
    mov     [checkSize2], ax	  ; was eax!! mjh 8/7/02
261 hidnplayr 899
 
900
    call    checksum
901
 
902
    ; store it in the UDP checksum ( in the correct order! )
903
    mov     ax, [checkResult]
904
 
905
    ; If the UDP checksum computes to 0, we must make it 0xffff
906
    ; (0 is reserved for 'not used')
914 serge 907
	test	ax, ax
908
	jnz	@f
261 hidnplayr 909
    mov     ax, 0xffff
910
 
914 serge 911
    @@: xchg	al, ah
912
	mov	[edx + 20 + UDP_PACKET.Checksum], ax
261 hidnplayr 913
 
914
    ; Fill in the IP header checksum
323 hidnplayr 915
    GET_IHL ecx,edx		 ; get IP-Header length
261 hidnplayr 916
    stdcall checksum_jb,edx,ecx  ; buf_ptr, buf_size
914 serge 917
	xchg	al, ah
918
	mov	[edx + IP_PACKET.HeaderChecksum], ax
261 hidnplayr 919
 
920
    ; Check destination IP address.
921
    ; If it is the local host IP, route it back to IP_RX
922
 
923
    pop     ebx
924
    mov     eax, NET1OUT_QUEUE
914 serge 925
	mov	ecx, [edx + SOCKET.RemoteIP]
261 hidnplayr 926
    mov     edx, [stack_ip]
927
    cmp     edx, ecx
914 serge 928
	jne	.not_local
261 hidnplayr 929
    mov     eax, IPIN_QUEUE
930
 
914 serge 931
  .not_local:
261 hidnplayr 932
    ; Send it.
933
    call    queue
934
 
935
    xor     eax, eax
914 serge 936
	ret
261 hidnplayr 937
 
914 serge 938
  .error:
939
	or	eax, -1
261 hidnplayr 940
    ret
914 serge 941
endp
261 hidnplayr 942
 
943
 
944
;***************************************************************************
945
;   Function
946
;      socket_write_tcp
947
;
948
;   Description
949
;       socket in ebx
950
;       # of bytes to write in ecx
951
;       pointer to data in edx
952
;       returns 0 in eax ok, -1 == failed ( invalid socket, or
953
;       could not queue IP packet )
954
;
955
;***************************************************************************
914 serge 956
proc socket_write_tcp stdcall
957
local sockAddr dd ?
261 hidnplayr 958
 
914 serge 959
;        DEBUGF  1, "socket_write_tcp(0x%x)\n", ebx
960
	stdcall net_socket_num_to_addr, ebx
961
	or	eax, eax
962
	jz	.error
261 hidnplayr 963
 
914 serge 964
	mov	ebx, eax
965
	mov	[sockAddr], ebx
966
 
261 hidnplayr 967
    ; If the socket is invalid, return with an error code
914 serge 968
	cmp	[ebx + SOCKET.Status], SOCK_EMPTY
969
	je	.error
261 hidnplayr 970
 
971
    ; If the sockets window timer is nonzero, do not queue packet
972
    ; TODO - done
914 serge 973
	cmp	[ebx + SOCKET.wndsizeTimer], 0
974
	jne	.error
261 hidnplayr 975
 
976
    mov     eax, EMPTY_QUEUE
977
    call    dequeue
978
    cmp     ax, NO_BUFFER
914 serge 979
	je	.error
261 hidnplayr 980
 
981
    push    eax
982
 
983
    ; Get the address of the callers data
379 serge 984
    mov     edi, [TASK_BASE]
261 hidnplayr 985
    add     edi, TASKDATA.mem_start
986
    add     edx, [edi]
987
    mov     esi, edx
988
 
989
    pop     eax
990
    push    eax
991
 
992
    push    ecx
914 serge 993
	mov	bl, TH_ACK
994
	stdcall build_tcp_packet, [sockAddr]
261 hidnplayr 995
    pop     ecx
996
 
997
    ; Check destination IP address.
998
    ; If it is the local host IP, route it back to IP_RX
999
 
1000
    pop     ebx
1001
    push    ecx
1002
    mov     eax, NET1OUT_QUEUE
1003
 
1004
    mov     edx, [stack_ip]
914 serge 1005
	mov	ecx, [sockAddr]
1006
	cmp	edx, [ecx + SOCKET.RemoteIP]
1007
	jne	.not_local
261 hidnplayr 1008
    mov     eax, IPIN_QUEUE
1009
 
914 serge 1010
  .not_local:
261 hidnplayr 1011
    pop     ecx
1012
 
323 hidnplayr 1013
    push    ebx 		; save ipbuffer number
261 hidnplayr 1014
 
1015
    call    queue
1016
 
914 serge 1017
	mov	esi, [sockAddr]
261 hidnplayr 1018
 
1019
    ; increament SND.NXT in socket
1020
    ; Amount to increment by is in ecx
914 serge 1021
	add	esi, SOCKET.SND_NXT
261 hidnplayr 1022
    call    add_inet_esi
1023
 
1024
    pop     ebx
1025
 
1026
    ; Copy the IP buffer to a resend queue
1027
    ; If there isn't one, dont worry about it for now
1028
    mov     esi, resendQ
1029
    mov     ecx, 0
1030
 
914 serge 1031
  .next_resendq:
261 hidnplayr 1032
    cmp     ecx, NUMRESENDENTRIES
914 serge 1033
	je	.exit		   ; None found
1034
	;cmp     byte[esi], 0xff                                 ; XTODO: 0xff -> 0
1035
	cmp	dword[esi + 4], 0
1036
	je	@f		   ; found one
261 hidnplayr 1037
    inc     ecx
914 serge 1038
	add	esi, 8
1039
	jmp	.next_resendq
261 hidnplayr 1040
 
914 serge 1041
    @@: push	ebx
261 hidnplayr 1042
 
1043
    ; OK, we have a buffer descriptor ptr in esi.
1044
    ; resend entry # in ecx
1045
    ;  Populate it
1046
    ;  socket #
1047
    ;  retries count
1048
    ;  retry time
1049
    ;  fill IP buffer associated with this descriptor
1050
 
914 serge 1051
	stdcall net_socket_addr_to_num, [sockAddr]
1052
	;mov     [esi], al                               ; XTODO: al -> eax
1053
	mov	[esi + 4], eax
1054
	mov	byte[esi + 1], TCP_RETRIES
1055
	mov	word[esi + 2], TCP_TIMEOUT
261 hidnplayr 1056
 
1057
    inc     ecx
1058
    ; Now get buffer location, and copy buffer across. argh! more copying,,
1059
    mov     edi, resendBuffer - IPBUFFSIZE
1060
 
914 serge 1061
    @@: add	edi, IPBUFFSIZE
1062
	loop	@b
1063
 
261 hidnplayr 1064
    ; we have dest buffer location in edi
1065
    pop     eax
1066
    ; convert source buffer pointer eax to the absolute address
1067
    mov     ecx, IPBUFFSIZE
1068
    mul     ecx
1069
    add     eax, IPbuffs
1070
    mov     esi, eax
1071
 
1072
    ; do copy
1073
    mov     ecx, IPBUFFSIZE
1074
    cld
1075
    rep     movsb
1076
 
914 serge 1077
  .exit:
261 hidnplayr 1078
    xor     eax, eax
914 serge 1079
	ret
261 hidnplayr 1080
 
914 serge 1081
  .error:
1082
	or	eax, -1
261 hidnplayr 1083
    ret
914 serge 1084
endp